normanius
normanius

Reputation: 9762

How to find out to which window the focus was passed on for a "WindowDeactivate" event?

By installing an event filter, it is possible to see if a window has been activated/deactivated (QtCore.QEvent.WindowActivate, QtCore.QEvent.WindowDeactivate).

class SomeWidget(QtWidgets.QWidget, object):
    # ...
    def __init__(self):
        # ...
        self.installEventFilter(self)
        # ...

    def eventFilter(self, object, event):
        if event.type() == QtCore.QEvent.WindowDeactivate:
            print('Window was deactivated.')
        if event.type() == QtCore.QEvent.WindowActivate:
            print('Window was activated.')

Is it possible to find out A) to which other window (of the same application) the focus was passed on, and B) whether the entire application was inactivated (that is: none of the windows is active)?

I wish the solution to be "minimal invasive" in that sense that I don't have to install event filters in all of my candidate windows. Is it possible to spy out other windows from within the current widget?

I'm interested in this information because I would like to capture some usage metrics for my application.

Upvotes: 2

Views: 601

Answers (1)

eyllanesc
eyllanesc

Reputation: 243887

If you want to monitor the status of the windows you can use the notify method of QApplication:

from PyQt5 import QtCore, QtWidgets


class Application(QtWidgets.QApplication):
    def notify(self, obj, event):
        if event.type() == QtCore.QEvent.WindowDeactivate:
            print("{} was deactivated:".format(obj))
        if event.type() == QtCore.QEvent.WindowActivate:
            print("{} was activated.".format(obj))
        return super().notify(obj, event)


if __name__ == "__main__":
    import sys

    app = Application(sys.argv)
    windows = []
    for _ in range(3):
        w = QtWidgets.QWidget()
        w.show()
        windows.append(w)
    sys.exit(app.exec_())

Using the previous method I have implemented a signal that sends the activated window with the function QApplication::activeWindow():

from PyQt5 import QtCore, QtWidgets


class Application(QtWidgets.QApplication):
    activateChanged = QtCore.pyqtSignal(QtWidgets.QWidget)

    def __init__(self, l):
        super().__init__(l)
        self._window_activate = None

    def notify(self, obj, event):
        if event.type() == QtCore.QEvent.WindowDeactivate:
            QtCore.QTimer.singleShot(0, self.on_timeout)
        if event.type() == QtCore.QEvent.WindowActivate:
            QtCore.QTimer.singleShot(0, self.on_timeout)
        return super().notify(obj, event)

    def on_timeout(self):
        if self._window_activate != QtWidgets.QApplication.activeWindow():
            self._window_activate = QtWidgets.QApplication.activeWindow()
            self.activateChanged.emit(self._window_activate)


if __name__ == "__main__":
    import sys

    app = Application(sys.argv)
    app.activateChanged.connect(print)
    windows = []
    for _ in range(5):
        w = QtWidgets.QWidget()
        w.show()
        windows.append(w)
    sys.exit(app.exec_())

Upvotes: 2

Related Questions