我有一个线程类“ MyThread”和主应用程序,简称为“ Gui”。我想从线程类创建一些对象,但在本示例中,我仅创建了一个对象。线程类完成一些工作,然后向Gui类发出信号,指示需要用户输入(此指示目前仅是更改按钮的文本)。然后,线程应等待用户输入(在这种情况下为单击按钮),然后继续执行其操作…
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_())
如何在(多个)线程中等待用户输入?
默认情况下,QThread具有事件循环,可以处理信号和插槽。在当前的实现中,很遗憾,您已通过重写删除了此行为QThread.run。如果还原它,则可以得到所需的行为。
QThread
QThread.run
因此,如果您不能覆盖QThread.run(),如何在Qt中进行线程处理?线程的另一种方法是将代码放在的子类中,QObject然后将该对象移至标准QThread实例。然后,您可以将信号和插槽连接在主线程和线程之间,QThread以双向通信。这将使您能够实现所需的行为。
QThread.run()
QObject
在下面的示例中,我启动了一个工作线程,该工作线程将打印到终端,等待2秒钟,再次打印,然后等待用户输入。单击该按钮时,工作线程中的第二个单独的函数运行,并以与第一次相同的模式打印到终端。请注意我使用moveToThread()和连接信号的顺序)。
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_()