1

In Windows 10, if I run the following test case GUI application from the command line ('python ./pyqt_freeze_testcase.py'), I see the following completely repeatable GUI freeze/hang/unresponsive behavior; every time the GUI becomes unresponsive, I can 'bring it back to life' by typing any key in the shell.

UPDATE: this seems to be triggered (and cured) by toggling the focus-follows-mouse-without-raising-the-window behavior; now the question becomes how to prevent freezes when focus-follows-mouse-without-raising is enabled. I posted a new question for that topic: PyQt5 GUI freeze caused by Windows focus-follows-mouse

The behavior is the same for the built-in shell ('cmd') and for PowerShell. Detailed script of actions and responses to illustrate the freeze is at the bottom of this post. How can I prevent the freeze / make sure the GUI application stays responsive?

pyqt_freeze_testcase.py:

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

import sys

# import the UI file created with pyuic5
from minimal_ui import Ui_Dialog

class MyWindow(QDialog,Ui_Dialog):
    def __init__(self,parent):
        QDialog.__init__(self)
        self.parent=parent
        self.ui=Ui_Dialog()
        self.ui.setupUi(self)

    def showMsg(self):
        self.really1=QMessageBox(QMessageBox.Warning,"Really?","Really do stuff?",
            QMessageBox.Yes|QMessageBox.No,self,Qt.WindowTitleHint|Qt.WindowCloseButtonHint|Qt.Dialog|Qt.MSWindowsFixedSizeDialogHint|Qt.WindowStaysOnTopHint)
        self.really1.show()
        self.really1.raise_()
        if self.really1.exec_()==QMessageBox.No:
            print("nope")
            return
        print("yep")

def main():
    app = QApplication(sys.argv)
    w = MyWindow(app)
    w.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

The GUI is just a dialog with a lineedit and a button (with signal/slot).

Accompanying UI file minimal_ui.py (from Qt Designer and pyuic5):

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'minimal.ui'
#
# Created by: PyQt5 UI code generator 5.8.2
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(400, 300)
        self.lineEdit = QtWidgets.QLineEdit(Dialog)
        self.lineEdit.setGeometry(QtCore.QRect(120, 90, 113, 22))
        self.lineEdit.setObjectName("lineEdit")
        self.pushButton = QtWidgets.QPushButton(Dialog)
        self.pushButton.setGeometry(QtCore.QRect(130, 150, 93, 28))
        self.pushButton.setObjectName("pushButton")

        self.retranslateUi(Dialog)
        self.pushButton.clicked.connect(Dialog.showMsg)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.pushButton.setText(_translate("Dialog", "PushButton"))

The detailed actions and responses, beginning from a new PowerShell:

  1. python ./pyqt_freeze_testcase.py
  2. move the GUI window so it is next to (not inside of) the PowerShell; reasoning is apparent below
  3. left click the lineedit and type some stuff --> said stuff shows up in the lineedit, as expected
  4. left click the pushbutton --> the 'Really?' QMessageBox appears
  5. left click anywhere in the PowerShell --> the PowerShell is raised, which would obscure the GUI application, which is the reason for step 2 above
  6. left click either 'Yes' or 'No' --> the messagebox closes, but, no output is shown in the shell, and, the GUI is unresponsive (it soon gets the spinner / hourglass, the banner says 'Dialog (Not Responding)' and you can't select the lineedit to type more stuff, and clicking the pushbutton does nothing; for all appearances, the GUI is frozen, but:
  7. left click anywhere in the PowerShell
  8. press any key --> the expected response (yep or nope) appears in the shell, and the GUI is now responsive again, i.e. you can repeat all of this starting at step 3; also note that any additional typing you may have done during the freeze will now appear in the lineedit
Tom Grundy
  • 736
  • 5
  • 26

2 Answers2

1

This is likely better as a comment but I don't have the reputation points to do so and some feedback is probably better for you than none.

I tested exactly what you did on my Windows 10 machine with both python3 and python2.7 and I can't replicate the situation you outlined in your question. Everything works as expected and the "nope" and "yep" messages appear immediately. You can try something like this: PySide / Python GUI freezes but a print statement shouldn't be freezing up your GUI and not printing in the console. You should definitely check a few other simple GUIs like yours to see what freezes and what doesn't. I would restart your computer first though. If that doesn't lead to any answers, maybe try reinstalling PyQt5.

aoh
  • 1,090
  • 2
  • 13
  • 25
  • that did actually help me find a more direct cause. I forgot that I had X-Mouse in play in order to mimic linux focus-follows-mouse-without-raising-the-window behavior (there a few different things called X-Mouse - this is the one from https://joelpurra.com/projects/X-Mouse_Controls/). Turning that off fixed it, i.e. the freeze behavior goes away and clicking in the terminal does not change anything. So I tried the similar registry mods from https://sinewalker.wordpress.com/2010/03/10/ms-windows-focus-follows-mouse-registry-hacks/ - they do still work on windows 10 - and that triggers it! – Tom Grundy Jun 30 '17 at 03:52
  • (continued comment) - so X-Mouse probably just does those same regedit lines. Without them, there is no freeze; with them; I get the freeze behavior described above. – Tom Grundy Jun 30 '17 at 03:53
  • So, it would be great if someone could try to reproduce this! Regardless, I will open a new question since the scope has changed quite a bit. Thanks! – Tom Grundy Jun 30 '17 at 03:54
0

The brute-force solution is working in the question linked to above (PyQt5 GUI freeze caused by Windows focus-follows-mouse); full code is posted there.

Hopefully someone can provide a more optimal or more 'correct' solution?

Basically, disable active window tracking in MainWindow init and restore to its initial setting in MainWindow closeEvent. Maybe a more optimal solution is out there, but, this one is short and reliable. The method from https://joelpurra.com/projects/X-Mouse_Controls/ takes effect immediately, whereas the registry hack does not take effect until reboot.

Tom Grundy
  • 736
  • 5
  • 26