如何在PySide GUI中检测鼠标点击?

4 投票
2 回答
8641 浏览
提问于 2025-04-18 08:05

我正在尝试实现一个功能,就是当我在图形界面上点击鼠标时,会触发一个函数。

下面是我用来检测鼠标点击的代码,但当我点击图形界面的任何部分时,它都没有反应。

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

import sys


class Main(QWidget):


    def __init__(self, parent=None):
        super(Main, self).__init__(parent)

        layout  = QHBoxLayout(self)
        layout.addWidget(QLabel("this is the main frame"))
        layout.gui_clicked.connect(self.anotherSlot)

    def anotherSlot(self, passed):
        print passed
        print "now I'm in Main.anotherSlot"


class MyLayout(QHBoxLayout):
    gui_clicked = Signal(str)

    def __init__(self, parent=None):
        super(MyLayout, self).__init__(parent)

    def mousePressEvent(self, event):
        print "Mouse Clicked"
        self.gui_clicked.emit("emit the signal")



a = QApplication([])
m = Main()
m.show()
sys.exit(a.exec_())

这是我的目标。

Mouseclick.gui_clicked.connect(do_something)

任何建议都非常感谢。

2 个回答

2

这件事可能会变得有点复杂,具体取决于你的需求。简单来说,解决方案是给应用程序安装一个eventFilter。这个过滤器会监听整个应用程序中的事件。问题在于“事件传播”。如果一个小部件(比如按钮或标签)没有处理某个事件,这个事件就会传递给它的父级(也就是包含它的窗口),然后再往上传。这样你可能会看到同一个事件被多次触发。例如,QLabel 对鼠标点击事件没有任何反应,所以这个事件就会传给它的父窗口(你的主窗口)。

如果你真的想过滤这个事件(也就是说,你不希望原来的小部件对这个事件做出反应),那么就不会出现这个问题。不过,我怀疑这是不是你的本意。

这里有一个简单的例子,展示如何监控事件:

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_())

你可以看到,点击 QLabel 会得到类似这样的输出:

mouse pressed <PySide.QtGui.QLabel object at 0x02B92490>
mouse pressed <__main__.MainWindow object at 0x02B92440>

这是因为 QLabel 收到了这个事件,但由于它没有处理这个事件,所以它被忽略了,并传递给了父窗口(MainWindow)。然后这个事件又被过滤器/监控器捕获到了。

点击 QPushButton 就没有问题,因为它会处理这个事件,而不会把它传递给父窗口。

PS: 另外要注意,这可能会导致性能问题,因为你在检查应用程序中的每一个事件。

3

Main里面定义一个mousePressEvent

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

import sys


class Main(QWidget):


    def __init__(self, parent=None):
        super(Main, self).__init__(parent)

        layout  = QHBoxLayout(self)
        layout.addWidget(QLabel("this is the main frame"))

    def mousePressEvent(self, QMouseEvent):
        #print mouse position
        print QMouseEvent.pos()


a = QApplication([])
m = Main()
m.show()
sys.exit(a.exec_())

撰写回答