pyqt5在终端中单击会导致GUI冻结 [英] pyqt5 click in terminal causes GUI freeze
问题描述
在Windows 10中,如果我从命令行运行以下测试用例GUI应用程序("python ./pyqt_freeze_testcase.py"),则会看到以下完全可重复的GUI冻结/挂起/无响应行为;每次GUI变得无响应时,我都可以通过在外壳中键入任何键来使其恢复活力".
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.
更新:这似乎是通过切换焦点跟随鼠标而不提高窗口行为来触发的(并且已解决);现在的问题变成了在启用焦点跟随鼠标而没有提升时如何防止冻结.我针对该主题发布了一个新问题:由Windows焦点跟随鼠标导致的PyQt5 GUI冻结
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
内置外壳('cmd')和PowerShell的行为相同.用于说明冻结的详细操作和响应脚本位于本文的底部.如何防止冻结/确保GUI应用程序保持响应状态?
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:
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和按钮(带有信号/插槽)的对话框.
The GUI is just a dialog with a lineedit and a button (with signal/slot).
随附的UI文件minimal_ui.py(来自Qt Designer和pyuic5):
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"))
从新的PowerShell开始的详细操作和响应:
The detailed actions and responses, beginning from a new PowerShell:
- python ./pyqt_freeze_testcase.py
- 移动GUI窗口,使其位于PowerShell旁边(不在PowerShell内部);推理在下面很明显
- 左键单击行编辑并输入一些内容 ->如预期的那样,这些内容会显示在lineedit中
- 左键单击按钮 ->真的吗?" QMessageBox出现
- 在PowerShell中的任意位置单击鼠标左键 ->生成了PowerShell,这会使GUI应用程序变得晦涩,这就是上面第2步的原因
- 左键单击是"或否" ->消息框关闭,但外壳中未显示任何输出,并且GUI没有响应(很快就会得到微调器/沙漏,横幅显示对话框(无响应)",并且您不能选择lineedit要键入更多内容,然后单击按钮则无济于事;对于所有外观,GUI都是冻结的,但是:
- 在PowerShell中的任意位置单击鼠标左键
- 按任意键 ->预期的响应(是或否)出现在外壳中,并且GUI现在再次响应,即,您可以从步骤3开始重复所有这些操作;还请注意,冻结期间您可能进行的其他任何输入现在都将显示在lineedit中
- python ./pyqt_freeze_testcase.py
- move the GUI window so it is next to (not inside of) the PowerShell; reasoning is apparent below
- left click the lineedit and type some stuff --> said stuff shows up in the lineedit, as expected
- left click the pushbutton --> the 'Really?' QMessageBox appears
- left click anywhere in the PowerShell --> the PowerShell is raised, which would obscure the GUI application, which is the reason for step 2 above
- 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:
- left click anywhere in the PowerShell
- 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
推荐答案
作为注释,这可能会更好,但是我没有信誉点,因此一些反馈对您来说总比没有好.
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.
我完全使用python3和python2.7测试了您在Windows 10机器上所做的事情,但我无法复制问题中概述的情况.一切正常,"nope"和"yep"消息立即出现.您可以尝试执行以下操作: PySide/Python GUI冻结,但不应打印声明冻结GUI而不在控制台中打印.您绝对应该检查其他一些简单的GUI,例如您的GUI,以查看冻结的内容和未冻结的内容.不过,我会先重新启动计算机.如果仍然无法解决问题,请尝试重新安装PyQt5.
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.
这篇关于pyqt5在终端中单击会导致GUI冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!