猿问

如何在 QCalendarWidget 中禁用其他月份

我的目标是禁用用户可以单击 aQCalendarWidget中非当前月份的日期,因此我将小部件子类化以执行此操作。到目前为止,我可以让那些日子根本不渲染任何文本(很棒)。这是代码:


class QCustomCalendar(QCalendarWidget):

    """Create my own Calendar with my own options."""


    def __init__(self, parent=None):

        """Initializing functions"""

        QCalendarWidget.__init__(self, parent)

        self.setEnabled(True)

        self.setGeometry(QRect(0, 0, 320, 250))

        self.setGridVisible(False)

        self.setHorizontalHeaderFormat(QCalendarWidget.SingleLetterDayNames)

        self.setVerticalHeaderFormat(QCalendarWidget.NoVerticalHeader)

        self.setNavigationBarVisible(True)

        self.setDateEditEnabled(True)

        self.setObjectName("calendarWidget")


    def paintCell(self, painter, rect, date):

        """Sub-class this and repaint the cells"""

        # Render only this-month days

        month = "{0}-{1}".format(str(self.yearShown()), str(self.monthShown()).zfill(2))

        day = str(date.toPython())

        if not day.startswith(month):

            return

        QCalendarWidget.paintCell(self, painter, rect, date)

但是,如果我单击未渲染的一天,它仍然会计数并触发clicked事件。示例:我对一个红色方块进行了 photoshop,点击它,它会选择 6 月 4 日(即使我们在屏幕截图中是在 5 月)。

我如何禁用那些日子不被选择?


我尝试setDateRange了currentPageChanged事件,但它没有按预期工作:


def __init__(self, parent=None):

    # some code

    self.currentPageChanged.connect(self.store_current_month)

    self.clicked.connect(self.calendar_itemchosen)


def store_current_month(self):

    self.CURRENT_MONTH = "{0}-{1}".format(str(self.yearShown()), str(self.monthShown()).zfill(2))


def calendar_itemchosen(self):

    day = str(self.selectedDate().toPython())

    print(day)

    if day.startswith(self.CURRENT_MONTH):

        selection = self.selectedDate()

        # some code

        self.close()

用这个代码点击那个红色方块的结果是:


2018-06

2018-06-04

所以我猜currentPageChanged当您选择另一个月份的日期时,Qt 首先会触发该事件。setDateRange将不起作用,因为如果我添加它以将选择限制在本月,那么日历顶部的“转到下个月或上个月”按钮将不起作用,我需要用户能够更改月份. 我只是不想让日历显示不属于这个月页面的日子。


梵蒂冈之花
浏览 394回答 1
1回答

倚天杖

一种解决方案是过滤 QCalendarWidget 内部具有的 QTableView 的 mousePressEvent 事件。为此,我们使用事件过滤器:from PyQt5 import QtCore, QtWidgetsclass CalendarWidget(QtWidgets.QCalendarWidget):&nbsp; &nbsp; def __init__(self, parent=None):&nbsp; &nbsp; &nbsp; &nbsp; super(CalendarWidget, self).__init__(parent, gridVisible=False,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; horizontalHeaderFormat=QtWidgets.QCalendarWidget.SingleLetterDayNames,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; verticalHeaderFormat=QtWidgets.QCalendarWidget.NoVerticalHeader,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; navigationBarVisible=True,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dateEditEnabled=True)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; self.setEnabled(True)&nbsp; &nbsp; &nbsp; &nbsp; self.setGeometry(QtCore.QRect(0, 0, 320, 250))&nbsp; &nbsp; &nbsp; &nbsp; self.clicked.connect(print)&nbsp; &nbsp; &nbsp; &nbsp; self.table_view = self.findChild(QtWidgets.QTableView, "qt_calendar_calendarview")&nbsp; &nbsp; &nbsp; &nbsp; self.table_view.viewport().installEventFilter(self)&nbsp; &nbsp; &nbsp; &nbsp; self.setFirstDayOfWeek(QtCore.Qt.Monday)&nbsp; &nbsp; def referenceDate(self):&nbsp; &nbsp; &nbsp; &nbsp; refDay = 1&nbsp; &nbsp; &nbsp; &nbsp; while refDay <= 31:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; refDate = QtCore.QDate(self.yearShown(), self.monthShown(), refDay)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if refDate.isValid(): return refDate&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; refDay += 1&nbsp; &nbsp; &nbsp; &nbsp; return QtCore.QDate()&nbsp; &nbsp; def columnForDayOfWeek(self, day):&nbsp; &nbsp; &nbsp; &nbsp; m_firstColumn = 1 if self.verticalHeaderFormat() != QtWidgets.QCalendarWidget.NoVerticalHeader else 0&nbsp; &nbsp; &nbsp; &nbsp; if day < 1 or day > 7: return -1&nbsp; &nbsp; &nbsp; &nbsp; column = day - int(self.firstDayOfWeek())&nbsp; &nbsp; &nbsp; &nbsp; if column < 0:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; column += 7&nbsp; &nbsp; &nbsp; &nbsp; return column + m_firstColumn&nbsp; &nbsp; def columnForFirstOfMonth(self, date):&nbsp; &nbsp; &nbsp; &nbsp; return (self.columnForDayOfWeek(date.dayOfWeek()) - (date.day() % 7) + 8) % 7&nbsp; &nbsp; def dateForCell(self, row, column):&nbsp; &nbsp; &nbsp; &nbsp; m_firstRow = 1 if self.horizontalHeaderFormat() != QtWidgets.QCalendarWidget.NoHorizontalHeader else 0&nbsp; &nbsp; &nbsp; &nbsp; m_firstColumn = 1 if self.verticalHeaderFormat() != QtWidgets.QCalendarWidget.NoVerticalHeader else 0&nbsp; &nbsp; &nbsp; &nbsp; rowCount = 6&nbsp; &nbsp; &nbsp; &nbsp; columnCount = 7&nbsp; &nbsp; &nbsp; &nbsp; if row < m_firstRow or row > (m_firstRow + rowCount -1) or column < m_firstColumn or column > (m_firstColumn + columnCount -1):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return QtCore.QDate()&nbsp; &nbsp; &nbsp; &nbsp; refDate = self.referenceDate()&nbsp; &nbsp; &nbsp; &nbsp; if not refDate.isValid():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return QtCore.QDate()&nbsp; &nbsp; &nbsp; &nbsp; columnForFirstOfShownMonth = self.columnForFirstOfMonth(refDate)&nbsp; &nbsp; &nbsp; &nbsp; if (columnForFirstOfShownMonth - m_firstColumn) < 1:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row -= 1&nbsp; &nbsp; &nbsp; &nbsp; requestedDay = 7*(row - m_firstRow) +&nbsp; column&nbsp; - columnForFirstOfShownMonth - refDate.day() + 1&nbsp; &nbsp; &nbsp; &nbsp; return refDate.addDays(requestedDay)&nbsp; &nbsp; def eventFilter(self, obj, event):&nbsp; &nbsp; &nbsp; &nbsp; if obj is self.table_view.viewport() and event.type() == QtCore.QEvent.MouseButtonPress:&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ix = self.table_view.indexAt(event.pos())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; date = self.dateForCell(ix.row(), ix.column())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d_start = QtCore.QDate(self.yearShown(), self.monthShown(), 1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d_end = QtCore.QDate(self.yearShown(), self.monthShown(), d_start.daysInMonth())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if d_start > date or date > d_end:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return True&nbsp; &nbsp; &nbsp; &nbsp; return super(CalendarWidget, self).eventFilter(obj, event)&nbsp; &nbsp; def paintCell(self, painter, rect, date):&nbsp; &nbsp; &nbsp; &nbsp; d_start = QtCore.QDate(self.yearShown(), self.monthShown(), 1)&nbsp; &nbsp; &nbsp; &nbsp; d_end = QtCore.QDate(self.yearShown(), self.monthShown(), d_start.daysInMonth())&nbsp; &nbsp; &nbsp; &nbsp; if d_start <= date <= d_end:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super(CalendarWidget, self).paintCell(painter, rect, date)if __name__ == '__main__':&nbsp; &nbsp; import sys&nbsp; &nbsp; app = QtWidgets.QApplication(sys.argv)&nbsp; &nbsp; w = CalendarWidget()&nbsp; &nbsp; w.show()&nbsp; &nbsp; sys.exit(app.exec_())
随时随地看视频慕课网APP

相关分类

Python
我要回答