PyQt4在线程中等待来自GUI的用户input
我有一个线程类“MyThread”和我的主要应用程序,简称为“桂”。 我想从线程类创build一些对象,但对于这个例子,我只创build了一个对象。 线程类做了一些工作,然后向Gui类发出一个信号,表示需要用户input(现在这个指示只是简单的改变一个button的文本)。 然后,线程应该等待用户input(在这种情况下点击一个button),然后继续做它正在做的事情…
from PyQt4 import QtGui, QtCore class MyTrhead(QtCore.QThread): trigger = QtCore.pyqtSignal(str) def run(self): print(self.currentThreadId()) for i in range(0,10): print("working ") self.trigger.emit("3 + {} = ?".format(i)) #### WAIT FOR RESULT time.sleep(1) class Gui(QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super(Gui, self).__init__(parent) self.setupUi(self) self.pushButton.clicked.connect(self.btn) self.t1 = MyTrhead() self.t1.trigger.connect(self.dispaly_message) self.t1.start() print("thread: {}".format(self.t1.isRunning())) @QtCore.pyqtSlot(str) def dispaly_message(self, mystr): self.pushButton.setText(mystr) def btn(self): print("Return result to corresponding thread") if "__main__" == __name__: import sys app = QtGui.QApplication(sys.argv) m = Gui() m.show() sys.exit(app.exec_())
我如何等待(多个)线程用户input?
默认情况下, QThread
有一个可以处理信号和插槽的事件循环。 在你当前的实现中,你不幸的通过覆盖QThread.run
移除这个行为。 如果你恢复它,你可以得到你想要的行为。
所以,如果你不能覆盖QThread.run()
,你怎么在Qt线程? 另一种线程化的方法是把你的代码放在QObject
一个子类中,并把这个对象移动到一个标准的QThread
实例上。 然后,您可以将主线程和QThread
之间的信号和插槽连接起来,以双向通信。 这将允许你实现你想要的行为。
在下面的例子中,我启动了一个工作线程,打印到terminal,等待2秒钟,再次打印,然后等待用户input。 单击button时,工作线程中的第二个独立函数将运行,并以与第一次相同的模式打印到terminal。 请注意我使用moveToThread()
的顺序,并连接信号(按照这个 )。
码:
from PyQt4.QtCore import * from PyQt4.QtGui import * import time class MyWorker(QObject): wait_for_input = pyqtSignal() done = pyqtSignal() @pyqtSlot() def firstWork(self): print 'doing first work' time.sleep(2) print 'first work done' self.wait_for_input.emit() @pyqtSlot() def secondWork(self): print 'doing second work' time.sleep(2) print 'second work done' self.done.emit() class Window(QWidget): def __init__(self, parent = None): super(Window, self).__init__() self.initUi() self.setupThread() def initUi(self): layout = QVBoxLayout() self.button = QPushButton('User input') self.button.setEnabled(False) layout.addWidget(self.button) self.setLayout(layout) self.show() @pyqtSlot() def enableButton(self): self.button.setEnabled(True) @pyqtSlot() def done(self): self.button.setEnabled(False) def setupThread(self): self.thread = QThread() self.worker = MyWorker() self.worker.moveToThread(self.thread) self.thread.started.connect(self.worker.firstWork) self.button.clicked.connect(self.worker.secondWork) self.worker.wait_for_input.connect(self.enableButton) self.worker.done.connect(self.done) # Start thread self.thread.start() if __name__ == "__main__": app = QApplication([]) w = Window() app.exec_()