0

In some cases on Windows platform, isActive() called on QWidget returns true, when, obviously, it cannot be active.

For example, my app doing much work on GUI thread and shows window with some delay after launch. If I launch app and switch to another application before app shows main window, when window will be showed, it will be definitely inactive. But calling isActive() returns true in this case. If I switch to my app and switch back to another app, isActive() will be false, as normal. But at first time it is true, which isn't what should normally be. On linux and OS X it works as planned, by the way.

How can I fix it? Or how can I workaround it?

Example code reproducing that issue given below. It's PyQt, but trust me, Qt reproduces this issue too.

import sys
from time import sleep
from PyQt5.QtWidgets import QWidget, QApplication

class BadWidget(QWidget):
    def __init__(self):
        super(BadWidget, self).__init__()
        self.startTimer(500)

    def timerEvent(self, e):
        print(self.isActiveWindow() and not self.isMinimized())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    bad_widget = BadWidget()
    sleep(1)
    bad_widget.show()
    app.exec_()
BOOtak
  • 109
  • 5

3 Answers3

2

Finally, I found some working solution which does exatly what I want. Unfortunately, it can be done only using WinAPI call, but it's OK.

The main idea is that on Windows, "active" and "foreground" window are not the same thing. More info here: https://stackoverflow.com/a/3940383/3400560

Final solution looks like this:

if sys.platform.startswith('win'):
    if ctypes.c_long(self.effectiveWinId()).value ==\
            windll.user32.GetForegroundWindow():
        # active
    else:
        # inactive
else:
    if self.isActiveWindow():
        # active
    else:
        # inactive
Community
  • 1
  • 1
BOOtak
  • 109
  • 5
0

Bad solution: call QApplication::processEvents() before requesting widget state.

Good solution: do "much work" in a thread pool via QtCuncurrent or other multi-threaded ways.

Dmitry Sazonov
  • 8,801
  • 1
  • 35
  • 61
  • This method shows interesting behaviour. I change sleep(1) to for loop with sleep(0.01) and call to processEvents(). With this changes, before Windows shows QWidget, application spams "False" in console, so, window is inactive and everything is great. But when QWidget appears, app starts logging "True", which means that window considering itself active, which is totally wrong. – BOOtak Mar 21 '15 at 07:12
  • I don't know python, so I can't help with debugging. – Dmitry Sazonov Mar 21 '15 at 07:35
0

You may try isVisible() && isActiveWindow() && !isMinimized()

Matt
  • 13,674
  • 1
  • 18
  • 27
  • isVisible() used to determine is Qwidget visible in terms of calling show()/hide() on it. isMinimized() has no effect, too. – BOOtak Mar 20 '15 at 17:16