Python 为什么我的PyQt用户界面没有冻结,而我没有';你没有循环吗?

Python 为什么我的PyQt用户界面没有冻结,而我没有';你没有循环吗?,python,qt,pyqt,pyqt4,Python,Qt,Pyqt,Pyqt4,我对Qt是相当陌生的。我已经使用Gtk3和内省以及GladeUI设计器在python中构建了一些东西,包括构建代码以在事件发生时作为函数运行。在GTK中,如果主循环当前没有循环,UI将冻结 现在,我正在努力学习PyQt。奇怪的是,我告诉窗口显示,UI出现,Python提示符返回。但是GUI并不像我对GTK所期望的那样被冻结(因为我没有运行主循环) 就从python解释器测试UI而言,这真的很好。但这怎么可能呢?Qt是否正在生成另一个正在循环的线程 代码如下: from PyQt4 import

我对Qt是相当陌生的。我已经使用Gtk3和内省以及GladeUI设计器在python中构建了一些东西,包括构建代码以在事件发生时作为函数运行。在GTK中,如果主循环当前没有循环,UI将冻结

现在,我正在努力学习PyQt。奇怪的是,我告诉窗口显示,UI出现,Python提示符返回。但是GUI并不像我对GTK所期望的那样被冻结(因为我没有运行主循环)

就从python解释器测试UI而言,这真的很好。但这怎么可能呢?Qt是否正在生成另一个正在循环的线程

代码如下:

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_multippp(object):
    def setupUi(self, multippp):
        multippp.setObjectName(_fromUtf8("multippp"))
        multippp.resize(371, 43)
        self.verticalLayout = QtGui.QVBoxLayout(multippp)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.label = QtGui.QLabel(multippp)
        self.label.setObjectName(_fromUtf8("label"))
        self.verticalLayout.addWidget(self.label)
        self.verticalLayout_2 = QtGui.QVBoxLayout()
        self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
        self.verticalLayout.addLayout(self.verticalLayout_2)

        self.retranslateUi(multippp)
        QtCore.QMetaObject.connectSlotsByName(multippp)

    def retranslateUi(self, multippp):
        multippp.setWindowTitle(QtGui.QApplication.translate("multippp", "Multiple PPP Accounts", None, QtGui.QApplication.UnicodeUTF8))
        self.label.setText(QtGui.QApplication.translate("multippp", "More than one PPP account found, please select one:", None, QtGui.QApplication.UnicodeUTF8))



import sys
app = QtGui.QApplication(sys.argv)
multippp = QtGui.QDialog()
ui = Ui_multippp()
ui.setupUi(multippp)
multippp.show()
# At this point the python prompt returns, but the UI is interactive. I can add/remove buttons at the python prompt.
这可能会有帮助:


“每个线程都可以有自己的事件循环。初始线程使用QCoreApplication::exec()启动其事件循环;其他线程可以使用QThread::exec()启动事件循环。与QCoreApplication一样,QThread提供一个exit(int)函数和一个quit()槽。”

,解释器提示符正在运行一个主循环,等待您的输入

PyQt不仅有一个主循环,通过运行
QCoreApplication.\u exec()
,可以启动该循环,而且还有它(就此而言,是pdb的主循环)。当解释器提示符旋转等待输入时,Qt事件正在被处理

例如,使用上述代码作为起点,您可以看到如果让解释器主循环花一段时间返回,接口将如何冻结:

from PyQt4 import QtCore, QtGui
import time

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_multippp(object):
    def setupUi(self, multippp):
        multippp.setObjectName(_fromUtf8("multippp"))
        multippp.resize(371, 43)
        self.verticalLayout = QtGui.QVBoxLayout(multippp)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.label = QtGui.QLabel(multippp)
        self.label.setObjectName(_fromUtf8("label"))
        self.verticalLayout.addWidget(self.label)
        self.verticalLayout_2 = QtGui.QVBoxLayout()
        self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
        self.verticalLayout.addLayout(self.verticalLayout_2)

        self.retranslateUi(multippp)
        QtCore.QMetaObject.connectSlotsByName(multippp)

    def retranslateUi(self, multippp):
        multippp.setWindowTitle(QtGui.QApplication.translate("multippp", "Multiple PPP Accounts", None, QtGui.QApplication.UnicodeUTF8))
        self.label.setText(QtGui.QApplication.translate("multippp", "More than one PPP account found, please select one:", None, QtGui.QApplication.UnicodeUTF8))



import sys
app = QtGui.QApplication(sys.argv)
multippp = QtGui.QDialog()
ui = Ui_multippp()
ui.setupUi(multippp)
multippp.show()
# UI is visible and interactive at this point
# But after the next command, the UI will freeze for 5 seconds while the interpreter loop is 'busy' waiting for the command to return
time.sleep(5)
当您尝试使用pdb进行调试时,会出现一个实际的副问题:Qt主循环连接到pdb提示符中,这使得您在执行类似于
pdb.set_trace()
的操作时尝试重新进入主循环。您将收到类似“QCoreApplication::exec:事件循环已在运行”的错误。为了能够使用pdb,您可以将其包装在
QtCore.pyqtRemoveInputHook()
QtCore.pyqtremoreInputhook()
中,这将允许您断开Qt与输入循环的连接,冻结它并进行调试


另请参见

能否发布一些示例代码?