我正在尝试检测我的gui上的鼠标点击,下面的代码允许在Qwidget的1层中检测鼠标点击
import sys
from PySide import QtGui, QtCore
class MouseDetector(QtCore.QObject):
def eventFilter(self, obj, event):
if event.type() == QtCore.QEvent.MouseButtonPress:
print 'mouse pressed', obj
return super(MouseDetector, self).eventFilter(obj, event)
class MainWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
layout = QtGui.QHBoxLayout()
layout.addWidget(QtGui.QLabel('this is a label'))
layout.addWidget(QtGui.QPushButton('Button'))
self.setLayout(layout)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mouseFilter = MouseDetector()
app.installEventFilter(mouseFilter)
main = MainWindow()
main.show()
sys.exit(app.exec_())
但是,如果我在Qwidget和Qwidget中嵌入了一个Qwidget,则鼠标点击不会穿透应用程序。
不仅如此,令人困惑的是,当我在内部小部件上安装事件过滤器时,鼠标点击仍然没有被检测到。
# Widget x.1 is embedded in Widget X
# -----------------Widget x.1-----------------------
# | |
# | |
# | ---------------------- ---------------------| |
# | | | | | |
# | | Widget x.1.1 | | | Widget x.1.2 |
# | | | | | |
# | ---------------------- ---------------------| |
# | |
# --------------------------------------------------
我接近解决方案是错误的吗?如有任何建议,不胜感激。
这是Qt中鼠标事件传播的预期行为。
QLabel和QPushButton默认接受鼠标事件,使用它们而不让它们传播到父类。您可以继承QWidget并覆盖鼠标交互方法而不接受事件,然后它们将传播。你可以在上面放一个透明的捕捉鼠标事件的小部件。
或者你可以使用你的事件过滤器。我运行程序,鼠标检测器运行正常(Windows 7, Python 2.7, PySide 1.2.2):
mouse pressed <PySide.QtGui.QPushButton object at 0x00000000038A0A88>
mouse pressed <PySide.QtGui.QLabel object at 0x00000000038A0908>
mouse pressed <__main__.MainWindow object at 0x00000000038A0888>
在其他捕获鼠标事件的所有内容之上的QWidget很容易完成。例如:from PySide import QtCore, QtGui
class ClickableWidget(QtGui.QWidget):
clicked = QtCore.Signal(QtGui.QMouseEvent)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def mousePressEvent(self, event):
self.clicked.emit(event)
event.ignore()
def beep():
print('button clicked')
def dup():
print('catcher clicked')
app = QtGui.QApplication([])
window = QtGui.QWidget()
button = QtGui.QPushButton('Click me', window)
button.clicked.connect(beep)
catcher = ClickableWidget(window)
catcher.clicked.connect(dup)
catcher.raise_()
window.show()
app.exec_()
这里按钮是可见的,但不能点击,因为另一个QWidget
(默认是透明的)在它上面(raise_()
)。实际上,即使没有信号,只是在上面放置一个小部件,它也会捕获所有鼠标事件,因为事件只传播到父级(并且捕获小部件不是这里按钮的子级)。另一种方法(忽略事件)有点棘手。参见Qt的顶级小部件与键盘和鼠标事件透明度?例如,