PyQt4 在线程中等待来自 GUI 的用户输入 [英] PyQt4 Wait in thread for user input from GUI

查看:20
本文介绍了PyQt4 在线程中等待来自 GUI 的用户输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个线程类MyThread"和我的主要应用程序,它简称为Gui".我想从线程类创建几个对象,但在这个例子中我只创建了一个对象.thread 类做了一些工作,然后向 Gui 类发出一个信号,指示需要用户输入(目前这个指示只是更改按钮的文本).然后线程应等待用户输入(在本例中为单击按钮),然后继续执行其正在执行的操作...

I have a thread class "MyThread" and my main application which is simply called "Gui". I want to create a few objects from the thread class but for this example I created only one object. The thread class does some work, then emits a signal to the Gui class, indicating that a user input is needed (this indication for now is simply changing the text of a button). Then the thread should wait for a user input (in this case a button click) and then continue doing what it is doing...

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_())

如何在(多个)线程中等待用户输入?

How can I wait in (multiple) threads for a user input?

推荐答案

默认情况下,QThread 有一个可以处理信号和槽的事件循环.在您当前的实现中,您不幸地通过覆盖 QThread.run 删除了此行为.如果你恢复它,你可以得到你想要的行为.

By default, a QThread has an event loop that can process signals and slots. In your current implementation, you have unfortunately removed this behaviour by overriding QThread.run. If you restore it, you can get the behaviour you desire.

所以如果你不能重写 QThread.run(),你如何在 Qt 中进行线程化?线程的另一种方法是将您的代码放在 QObject 的子类中,然后将该对象移动到标准的 QThread 实例中.然后,您可以将主线程和 QThread 之间的信号和插槽连接在一起,以进行双向通信.这将允许您实现您想要的行为.

So if you can't override QThread.run(), how do you do threading in Qt? An alternative approach to threading is to put your code in a subclass of QObject and move that object to a standard QThread instance. You can then connect signals and slots together between the main thread and the QThread to communicate in both directions. This will allow you to implement your desired behaviour.

在下面的示例中,我启动了一个工作线程,它打印到终端,等待 2 秒,再次打印,然后等待用户输入.单击按钮时,工作线程中的第二个单独函数将运行,并以与第一次相同的模式打印到终端.请注意我使用 moveToThread() 和连接信号的顺序(根据 this).

In the example below, I've started a worker thread which prints to the terminal, waits 2 seconds, prints again and then waits for user input. When the button is clicked, a second separate function in the worker thread runs, and prints to the terminal in the same pattern as the first time. Please note the order in which I use moveToThread() and connect the signals (as per 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_()

这篇关于PyQt4 在线程中等待来自 GUI 的用户输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆