0

私はQtにかなり慣れていません。イベントが発生したときに実行される関数として実行されるコードの構築など、イントロスペクションを備えた Gtk3 と Glade UI デザイナーを使用して Python でいくつかのものを構築しました。GTK では、メイン ループが現在ループしていない場合、UI がフリーズします。

今、私は PyQt を学ぼうとしています。奇妙に思えるのは、ウィンドウに表示するように指示すると、UI が表示され、Python プロンプトが返されることです。しかし、GTK で期待するように GUI はフリーズしません (メイン ループが実行されていないため)。

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.
4

2 に答える 2

0

考えてみれば、インタプリタ プロンプトは、入力を待っているメイン ループを実行しています。

PyQt には、 を実行することによって開始されるメイン ループがあるだけでなく、インタープリター プロンプトのメイン ループ (さらに言えば、pdb のメイン ループ)QCoreApplication._exec()にもフックされます。インタープリター プロンプトが入力を待って円を描いて回転している間、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: The event loop is already running」のようなエラーが表示されます。pdb を使用できるようにするには、それをQtCore.pyqtRemoveInputHook()andでラップしQtCore.pyqtRestoreInputHook()ます。これにより、Qt を入力ループから切り離し、フリーズしてデバッグできるようになります。

http://www.riverbankcomputing.com/pipermail/pyqt/20​​07-September/017134.htmlも参照してください。

于 2013-05-21T04:08:56.143 に答える