如果单击按钮,则获取鼠标位置不起作用

Getting mouse position doesn't work if button is clicked

每当按下鼠标左键时,我都在尝试获取鼠标位置(in-window):

def mousePressEvent(self, event):
        print(event.pos())

但是,任何类型的交互式小部件都会覆盖它,例如 - 单击按钮不会打印鼠标位置,与行编辑和其他(可能除了标签)一样。即使单击了这些小部件,我如何获得鼠标位置?

解释:

对于 QWidgets,您必须考虑:

  • 鼠标事件的传输是从顶部的widget(child)到底部的widget(parent)。

  • 如果一个元素消耗了鼠标事件(即使用event.accept()),那么该事件将不再被传输。

解决方案:

如果您想在 window 上检测鼠标事件,那么您可以通过事件过滤器在 window 本身 (QWindow) 上监视该事件:

import sys

from PyQt5.QtCore import pyqtSignal, QEvent, QObject, QPoint
from PyQt5.QtWidgets import (
    QApplication,
    QLineEdit,
    QPushButton,
    QTextEdit,
    QVBoxLayout,
    QWidget,
)


class MouseHelper(QObject):
    pressed = pyqtSignal(QPoint)
    released = pyqtSignal(QPoint)

    def __init__(self, window):
        super().__init__(window)
        self._window = window

        self.window.installEventFilter(self)

    @property
    def window(self):
        return self._window

    def eventFilter(self, obj, event):
        if self.window is obj:
            if event.type() == QEvent.MouseButtonPress:
                self.pressed.emit(event.pos())
            elif event.type() == QEvent.MouseButtonRelease:
                self.released.emit(event.pos())
        return super().eventFilter(obj, event)


class Widget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        button = QPushButton("Press me")
        lineedit = QLineEdit()
        textedit = QTextEdit()

        lay = QVBoxLayout(self)
        lay.addWidget(button)
        lay.addWidget(lineedit)
        lay.addWidget(textedit)


if __name__ == "__main__":
    app = QApplication(sys.argv)

    w = Widget()
    w.show()

    helper = MouseHelper(w.windowHandle())
    helper.pressed.connect(lambda point: print("pressed:", point))
    helper.released.connect(lambda point: print("released:", point))

    sys.exit(app.exec_())