我有一个线程类" 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_())
如何在(多个)线程中等待用户输入?
答案 0 :(得分:8)
默认情况下,QThread
有一个可以处理信号和插槽的事件循环。在您当前的实现中,遗憾的是,通过覆盖QThread.run
来删除此行为。如果你恢复它,你可以得到你想要的行为。
所以如果你不能覆盖QThread.run()
,你如何在Qt中进行线程化?另一种线程方法是将代码放在QObject
的子类中,并将该对象移动到标准QThread
实例。然后,您可以在主线程和QThread
之间将信号和插槽连接在一起,以便在两个方向上进行通信。这将允许您实现所需的行为。
在下面的例子中,我启动了一个工作线程,它打印到终端,等待2秒,再次打印,然后等待用户输入。单击该按钮时,工作线程中的第二个单独函数运行,并以与第一次相同的模式打印到终端。请注意我使用moveToThread()
的顺序并连接信号(根据this)。
代码:
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_()