pyqt5单击终端会导致GUI冻结

时间:2017-06-29 14:32:07

标签: pyqt freeze

在Windows 10中,如果我从命令行运行以下测试用例GUI应用程序(' python ./pyqt_freeze_testcase.py'),我会看到以下完全可重复的GUI冻结/挂起/无响应行为;每次GUI变得反应迟钝时,我都可以将它恢复生机。通过在shell中键入任何键。

UPDATE:这似乎是通过切换焦点跟随鼠标而不是提升窗口行为来触发(和治愈);现在问题变成了如何在启用焦点跟随鼠标而不启动时防止冻结。我针对该主题发布了一个新问题:PyQt5 GUI freeze caused by Windows focus-follows-mouse

内置shell(' cmd')和PowerShell的行为相同。用于说明冻结的详细操作和响应脚本位于本文的底部。如何防止冻结/确保GUI应用程序保持响应?

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()

GUI只是一个带有lineedit和按钮(带信号/插槽)的对话框。

随附UI文件minimal_ui.py(来自Qt Designer和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"))

详细的操作和响应,从新的PowerShell开始:

  1. python ./pyqt_freeze_testcase.py
  2. 移动GUI窗口,使其位于PowerShell旁边(不在其内部);推理显然在下面
  3. 左键单击lineedit并输入一些内容 - >正如预期的那样,所说的东西出现在lineedit中
  4. 左键单击按钮 - >真的吗?'出现QMessageBox
  5. 左键单击PowerShell中的任意位置 - >引发了PowerShell,这会模糊GUI应用程序,这就是上面第2步的原因
  6. 左键单击“是”'或者'否' - >消息框关闭,但是,shell中没有显示输出,并且GUI没有响应(很快就会获得微调器/沙漏,横幅显示'对话框(无响应)'并且您可以' ; t选择lineedit以输入更多内容,单击按钮不会执行任何操作;对于所有外观,GUI都会冻结,但是:
  7. 左键单击PowerShell中的任意位置
  8. 按任意键 - >预期的响应(是或否)出现在shell中,GUI现在再次响应,即你可以从步骤3开始重复所有这些;另请注意,您在冻结期间可能进行的任何其他输入现在都会出现在lineedit

2 个答案:

答案 0 :(得分:0)

这可能更适合作为评论,但我没有声誉点这样做,而且一些反馈对你来说可能比没有更好。

我使用python3和python2.7测试了你在我的Windows 10机器上做了什么,我无法复制你在问题中列出的情况。一切都按预期工作," nope"和"是的"消息立即出现。您可以尝试这样的事情:PySide / Python GUI freezes但是打印声明不应该冻结您的GUI而不是在控制台中打印。你一定要检查一下像你这样的其他一些简单的图形用户界面,看看有什么冻结,什么不是。我会先重启你的电脑。如果这不能导致任何答案,可以尝试重新安装PyQt5。

答案 1 :(得分:0)

蛮力解决方案正在解决与上述相关的问题(PyQt5 GUI freeze caused by Windows focus-follows-mouse);完整的代码发布在那里。

希望有人可以提供更优或更正确的信息。溶液

基本上,在MainWindow init 中禁用活动窗口跟踪,并在MainWindow closeEvent中恢复其初始设置。也许有更优化的解决方案,但是,这个解决方案简短而可靠。 https://joelpurra.com/projects/X-Mouse_Controls/的方法立即生效,而注册表黑客在重启之前不会生效。