PyQt wheelEvent重定向和超出的最大递归深度

时间:2016-10-21 23:44:55

标签: events recursion pyqt mouseevent pyqt5

我在QDialog中有一个QListWidget,我想将所有轮事件重定向到列表,所以我这样做了:

class Form(QDialog):
    def __init__(self):
    ...
        self.myList = QListWidget()
    ...
    def wheelEvent(self, scrollEvent):
        if not scrollEvent.isAccepted():
            scrollEvent.accept()
            self.myList.wheelEvent(scrollEvent)

它可以正常工作,直到滚动操作尝试将列表移动到其限制之外。似乎在那些情况下,QListWidget不接受(忽略)滚动事件并将其(忽略)传送给它的父,Form,它再次将它再次发送到QListWidget,直到“超出最大递归深度”提出错误消息。

如果事件在被重定向到QListWidget之前被接受,为什么当它返回到Qdialog时会再次重定向到QListWidget?似乎事件的“accept”标志未被保留(或者QListWidget将其设置回“不被接受”),并且当它返回QDialog时被视为新事件。即使列表位于顶部/底部,我如何保留这些标志或使QListWidget接受事件?

我试图定义一个QListWidget的子类,并在将其重定向到超类之前接受该子类的事件,但同样的结果,该事件返回到Dialog,因为不被接受。

编辑:再次嗨!我找到了解决方案:

class Form(QDialog):
    def __init__(self):
    ...
        self.processingWheel = False
        self.myList = QListWidget()
    ...
    def wheelEvent(self, scrollEvent):
        if not self.processingWheel:
            self.processingWheel = True
            self.myList.wheelEvent(scrollEvent)
            self.processingWheel = False

现在,当QListWidget不处理事件时(导致列表位于顶部/底部),事件再次到达QDialog,但第二次没有再次重定向到QListWidget。我想它被重定向到QDialog父级,并且它已被处理(什么都不做)。

如果允许,我想让问题保持开放,因为我仍然想知道为什么我必须自己管理该标志,并且无法使用与该事件相关联的isAccepted()标志。尝试。我担心在Qt中的事件传播期间我没有理解事件标志背后发生的事情。

1 个答案:

答案 0 :(得分:1)

注意:这适用于Qt5 - 在Qt4中,事情可能会有所不同。

当您致电self.myList.wheelEvent(scrollEvent)时,会在内部调用QListView.wheelEvent(event),这将创建一个新的QWheelEvent,并将其转发到相应的滚动条窗口小部件。如果滚动条无法处理该事件,则会将接受的标志设置为false。这将导致事件立即重新传播到对话框,整个事情将再次出现。

将事件发送到list-widget后,在myList.wheelEvent()返回之前,您无法重新设置accept标志。但是,当然,如果list-widget的滚动条忽略了该事件,它永远不会返回,因为它会立即进入无限回归。

在转发事件之前调用event.flag()将无效,因为默认情况下滚动条将其重置为false,并且只有在显式处理事件时才将其设置为true。

鉴于这一切,使用外部标志的解决方案似乎是唯一可行的解​​决方案(它有点类似于blockSignals机制)。