首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PyQt5 -我如何在QDateEdit上禁用周末

PyQt5 -我如何在QDateEdit上禁用周末
EN

Stack Overflow用户
提问于 2021-11-05 14:03:18
回答 1查看 236关注 0票数 0

我正在使用QDateEdit来选择一个特定的日期,但我想取消周末,我只想选择一周的日子。

代码语言:javascript
复制
self.date =  QDateEdit(calendarPopup = True)
self.date.setDisplayFormat("dd-MM-yyyy")
self.date.setMinimumDate(QDate(2021,10,1))    
self.date.setDate(QDate(datetime.today()))
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-05 16:02:08

QCalendarWidget只允许单个接受日期,并且可以选择该范围内的所有日期。

我能想到的唯一解决方案(除了从头创建自己的日历)是子类QCalendarWidget,访问底层的QTableView (显示日历)并执行以下操作:

将选择模式设置为NoSelection;

  • install事件筛选器(用于过滤按下键)和视图的视口(筛选鼠标events);

  • implement a dateForIndex以在表的特定索引处检索显示日期;

  • 将鼠标位置上的索引设置为SingleSelection,否则将其设置为NoSelection;

  • implement适当选择,以避免/跳过周末时使用键盘导航;

)

代码语言:javascript
复制
class CalendarWidget(QtWidgets.QCalendarWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setSelectionMode(self.NoSelection)
        self.view = self.findChild(QtWidgets.QAbstractItemView, 'qt_calendar_calendarview')
        self.view.installEventFilter(self)
        self.view.viewport().installEventFilter(self)

    def dateForIndex(self, index):
        row = index.row()
        column = index.column()
        if self.horizontalHeaderFormat():
            row -= 1
        if self.verticalHeaderFormat():
            column -= 1
        if not 0 <= row <= 5 or not 0 <= column <= 6:
            return QtCore.QDate()

        day = index.data()
        month = self.monthShown()
        year = self.yearShown()

        # day numbers bigger than 21 cannot be shown in the first 3 rows
        if row <= 2 and day > 21:
            month -= 1
            if month <= 0:
                month = 12
                year -= 1
        # day numbers smaller than 15 cannot be shown in the last 3 rows
        elif row >= 3 and day < 15:
            month += 1
            if month >= 13:
                month = 1
                year += 1

        date = QtCore.QDate(year, month, day)
        if self.minimumDate() <= date <= self.maximumDate():
           return date
        return QtCore.QDate()

    def moveCursor(self, key):
        currentDate = self.dateForIndex(self.view.currentIndex())
        delta = 1

        if key == QtCore.Qt.Key_Up:
            newDate = currentDate.addDays(-7)
        elif key == QtCore.Qt.Key_Down:
            newDate = currentDate.addDays(7)
        elif key == QtCore.Qt.Key_Left:
            newDate = currentDate.addDays(-1)
        elif key == QtCore.Qt.Key_Right:
            newDate = currentDate.addDays(1)
        elif key == QtCore.Qt.Key_Home:
            newDate = QtCore.QDate(currentDate.year(), currentDate.month(), 1)
            delta = -1
        elif key == QtCore.Qt.Key_End:
            newDate = QtCore.QDate(currentDate.year(), currentDate.month(), 
                currentDate.daysInMonth())
            delta = -1
        elif key == QtCore.Qt.Key_PageUp:
            newDate = currentDate.addMonths(-1)
            delta = -1
        elif key == QtCore.Qt.Key_PageDown:
            newDate = currentDate.addMonths(1)
            delta = -1
        else:
            return

        newDate = max(self.minimumDate(), min(newDate, self.maximumDate()))
        if currentDate != newDate:
            # if it's a day of the weekend, add the delta until a work day is
            # found; for Home/End/Page keys the delta is inverted, as we need to
            # ensure that we stay in the days of the selected month, and if the
            # function reaches a weekend it could skip a month
            while newDate.dayOfWeek() > 5:
                if newDate > currentDate:
                    newDate = newDate.addDays(delta)
                else:
                    newDate = newDate.addDays(-delta)
            if self.minimumDate() <= newDate <= self.maximumDate():
                return newDate

    def eventFilter(self, obj, event):
        if (event.type() in (event.MouseButtonPress, event.MouseButtonRelease, event.MouseButtonDblClick) 
            and event.button() == QtCore.Qt.LeftButton):
                index = self.view.indexAt(event.pos())
                if index.isValid():
                    date = self.dateForIndex(index)
                    if date.dayOfWeek() <= 5:
                        self.setSelectionMode(self.SingleSelection)
                    else:
                        self.setSelectionMode(self.NoSelection)

        elif event.type() == event.MouseMove and event.buttons() == QtCore.Qt.LeftButton:
            index = self.view.indexAt(event.pos())
            if index.isValid():
                date = self.dateForIndex(index)
                if not date.isValid() or date.dayOfWeek() > 5:
                    # ignore mouse move events for weekends
                    return True

        elif event.type() == event.KeyPress:
            newDate = self.moveCursor(event.key())
            if newDate:
                self.setSelectedDate(newDate)
                return True
        return super().eventFilter(obj, event)

这个实现的唯一问题是,如果设置了dateEditEnabled (这是默认的),除了连接到activatedselectionChanged信号并最终将选定的日期重置为有效的日期之外,没有办法阻止选择周末。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69854479

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档