Skip to content Skip to sidebar Skip to footer

Get Mouse Press Event From ANY Widget

I have a QMainWindow application that has multiple widgets (buttons, labels, etc.) inside it. How can I get an event when the user presses ANYWHERE of the app? I tried to customize

Solution 1:

Explanation:

The handling of mouse events between the widgets goes from children to parents, that is, if the child does not accept the event (it does not use it) then it will pass the event to the parent. For example, if you press on the QPushButton, it accepts the event and the parent is not notified, unlike QLabel that does not consume it, so the event passes to the parent.

Tools:

On the other hand, there are several methods to listen to events in general, such as:

  • Override any method like mousePressEvent, keyPressEvent, etc or the event or customEvent method.

  • Use an eventFilter.

Answer :

An alternative is to apply some previous method to all the widgets but you can discard all of them for the current objective, for example:

  • In the first and second method it would involve detecting when a widget is added or removed (using QEvent::ChildAdded or QEvent::ChildRemoved).

  • In the first method it would imply override the methods that many times is impossible.

With the above, the problem is attacked on the widgets side, but there are other alternatives:

  • Override the notify() method of Q{Core, GUi,}Application, verify that it is a widget and that it belongs to the window, it also implies discriminating if the event has already been consumed.

  • Listen to the mouse event associated with the window (QWindow).

In this case the most reasonable is the second method.

import sys

from PyQt5 import QtCore, QtWidgets


class MouseObserver(QtCore.QObject):
    pressed = QtCore.pyqtSignal(QtCore.QPoint)
    released = QtCore.pyqtSignal(QtCore.QPoint)
    moved = QtCore.pyqtSignal(QtCore.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() == QtCore.QEvent.MouseButtonPress:
                self.pressed.emit(event.pos())
            elif event.type() == QtCore.QEvent.MouseMove:
                self.moved.emit(event.pos())
            elif event.type() == QtCore.QEvent.MouseButtonRelease:
                self.released.emit(event.pos())
        return super().eventFilter(obj, event)


class MainWindow(QtWidgets.QMainWindow):
    pass


def main(args):
    app = QtWidgets.QApplication(args)

    w = MainWindow()
    w.show()

    mouse_observer = MouseObserver(w.window().windowHandle())
    mouse_observer.pressed.connect(lambda pos: print(f"pressed: {pos}"))
    mouse_observer.released.connect(lambda pos: print(f"released: {pos}"))
    mouse_observer.moved.connect(lambda pos: print(f"moved: {pos}"))

    app.exec_()


if __name__ == "__main__":
    main(sys.argv)

Post a Comment for "Get Mouse Press Event From ANY Widget"