我希望能够在QScrollArea中使用鼠标滚动,无论鼠标是否位于禁用的QToolButton上方。文档提到禁用的小部件不会将鼠标事件传播给父母,我想出来我需要安装事件过滤器来克服我遇到的这个问题。这是我设法做到这一点。我认为在检测到wheel事件时安装了事件过滤器,但我不确定接下来的步骤应该是什么:
/
答案 0 :(得分:2)
一旦捕获到正确的事件,您需要将事件发布到父窗口小部件。我之前做过这样的事情:
def eventFilter(self, obj, event):
if obj and not obj.isEnabled() and event.type() == QEvent.Wheel:
newEvent = QWheelEvent(obj.mapToParent(event.pos()), event.globalPos(),
event.delta(), event.buttons(),
event.modifiers(), event.orientation())
QApplication.instance().postEvent(obj.parent(), newEvent)
return True
return QObject.eventFilter(self, obj, event)
如果禁用该按钮且事件类型为QEvent.Wheel
,则此事件过滤器仅执行某些操作。否则,它会实现eventFilter
的默认行为。
if语句中的登录首先将坐标映射到父窗口小部件,然后构造具有与原始事件相同的参数的新QWEheelEvent
(坐标映射除外)。最后一部分是获取QApplication
的实例并使用postEvent
方法将事件发送到Qt事件循环,其中Qt将事件分发到适当的小部件(残疾人的父级)按钮)。
答案 1 :(得分:0)
我认为面向对象的编程风格在PySide和解决这样的问题时是合适的。如果将来PySide初学者偶然发现这个答案,那么就是如何让它成功的完整例子:
from PySide import QtGui
from PySide.QtCore import *
import sys
# http://zetcode.com/gui/pysidetutorial/firstprograms/
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.scroll = QtGui.QScrollArea()
self.scroll.setWidget(self)
self.layout = QtGui.QVBoxLayout()
self.setLayout(self.layout)
self.btn = QtGui.QToolButton()
self.btn.move(50, 50)
self.btn.setEnabled(False)
self.btn.installEventFilter(self)
self.layout.addWidget(self.btn)
self.setGeometry(300, 300, 250, 150)
self.scroll.show()
def eventFilter(self, obj, event):
if obj and not obj.isEnabled() and event.type() == QEvent.Wheel:
newEvent = QtGui.QWheelEvent(obj.mapToParent(event.pos()), event.globalPos(),
event.delta(), event.buttons(),
event.modifiers(), event.orientation())
QtGui.QApplication.instance().postEvent(obj.parent(), newEvent)
print "QEvent: " + str(event.type())
return True
return QObject.eventFilter(self, obj, event)
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()