鼠标点击是否穿过Qwidgets进入到应用程序的内部?



我正在尝试检测我的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的顶级小部件与键盘和鼠标事件透明度?例如,

相关内容

  • 没有找到相关文章

最新更新