带有拦截鼠标点击的自定义 QCalendarWidget 的 QDateTimeEdit?

A QDateTimeEdit with a custom QCalendarWidget that intercepts mouse clicks?

根据 PySide docs:

QDateTimeEdit can be configured to allow a QCalendarWidget to be used to select dates. This is enabled by setting the QDateTimeEdit.calendarPopup() property. Additionally, you can supply a custom calendar widget for use as the calendar pop-up by calling the QDateTimeEdit.setCalendarWidget() function. The existing calendar widget can be retrieved with QDateTimeEdit.calendarWidget().

太棒了,我可以做到,但我的问题是它有什么用?自定义日历小部件似乎无法拦截鼠标点击或绘画事件,在我看来,这似乎是您想要使用自定义日历小部件执行的操作。无论如何,这是我想做的。我写了一个快速脚本来测试这个:

from PySide.QtGui import *
from PySide.QtCore import *

import sys 

class EventLogger(QObject):
    def __init__(self, **kwargs):
        super(EventLogger, self).__init__(**kwargs)

    def eventFilter(self, obj, event):
        print "Object = %s; event = %s" % (type(obj).__name__, event.type())
        return False

class MyCalendar(QCalendarWidget):
    def __init__(self, **kwargs):
        super(MyCalendar, self).__init__(**kwargs)
        self.installEventFilter(EventLogger(parent=self))
        print "*** Initializing custom calendar widget ***"

    def mousePressEvent(self, e): 
        print "*** Intercepting mouse press event ***"

class MyWidget(QWidget):
    def __init__(self, **kwargs):
        super(MyWidget, self).__init__(**kwargs)
        self._initUI()

        self.show()
        self.setFocus()
        self.raise_()

    def _initUI(self):
        layout = QGridLayout()
        self.setLayout(layout)

        de = QDateTimeEdit()
        de.setCalendarPopup(True)
        de.setCalendarWidget(MyCalendar(parent=de))
        layout.addWidget(de, 0, 0, 1, 1)

def main():
    app = QApplication([])
    mw = MyWidget()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

运行 这个,打开日历,点击一个日期,然后退出程序输出:

*** Initializing custom calendar widget *** 
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.ParentChange
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.Polish
Object = MyCalendar; event = PySide.QtCore.QEvent.Type(70)
Object = MyCalendar; event = PySide.QtCore.QEvent.Type(70)
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.ChildPolished
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.ChildPolished
Object = MyCalendar; event = PySide.QtCore.QEvent.Type(67)
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.PolishRequest
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.LayoutRequest
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.Move
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.Resize
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.Show
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.ShowToParent
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.LayoutRequest
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.Enter
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.Hide
Object = MyCalendar; event = PySide.QtCore.QEvent.Type.Leave
Object = QWidget; event = PySide.QtCore.QEvent.Type.DynamicPropertyChange
Object = QWidget; event = PySide.QtCore.QEvent.Type.ChildRemoved

值得注意的是缺少鼠标点击和绘画事件,并且 mousePressEvent() 函数未被调用。那么真正定制它的最简单方法是什么?我是否必须自己重新实现 QDateTimeEdit/QCalendarWidget?文档说您可以自定义日历,但没有提供任何有关如何正确执行此操作的详细信息,甚至没有提供您想要的原因,因为它显然在这种情况下可以执行的操作受到限制。

好吧,回答我自己的问题,正确的方法是 不是 通过拦截鼠标点击和绘画事件,而是使用 paintCell() method and the clicked 信号,每个tmoreau 的评论。我想这有点违反直觉,但是 paintCell() 方法会为您提供每天的矩形,这很方便。