【问题标题】:Python sending signals between two QThreadsPython 在两个 QThread 之间发送信号
【发布时间】:2018-03-13 21:07:52
【问题描述】:

我无法将信号从一个 qthread 发送到另一个。我正在使用的类似代码摘录如下:

class auth(QtCore.QThread):
    authenticate = pyqtSignal()
    serverDown = pyqtSignal()
    accntonline = pyqtSignal()

    def __init__(self, parent=None):
        super(auth, self).__init__(parent)
    def run(self):
        self.authenticate.emit()

class Threadclass(QtCore.QThread):
    authenticator = "n"
    def __init__(self, parent=None):

        super(Threadclass, self).__init__(parent)
        #setting first values avoiding errors

        self.a = auth(self)

        self.a.authenticate.connect(self.setauthentication)

    #All small functions setting values from box.

    def setauthentication(self):
        print("awdawdawda")
        self.authenticator = "y"

当我运行线程验证时,变量self.authenticator 不会改变。它停留在“n”。 感谢所有帮助

【问题讨论】:

  • 如果你重写了QThreadrun 方法,它不会启动自己的事件循环,除非你显式调用它的exec 方法。处理跨线程信号需要事件循环。因此,通常最好创建一个工作对象并将其移动到线程,而不是覆盖run
  • @ekhumoro 有用的信息。如果您可以使用我提供的代码提供示例,是否有可能?
  • 我已根据您的示例代码添加了答案。希望您能看到如何调整它以用于您的实际应用程序。

标签: python pyqt signals qthread


【解决方案1】:

如果你重写 QThreadrun 方法,它不会启动自己的事件循环,除非你显式调用它的 exec 方法。处理跨线程信号需要事件循环。因此,通常最好创建一个工作对象并将其移至线程,而不是覆盖run

这是一个演示脚本,展示了如何将工作对象与线程一起使用:

import sys
from PyQt5 import QtWidgets, QtCore

class AuthWorker(QtCore.QObject):
    authenticate = QtCore.pyqtSignal()

    def __init__(self):
        super(AuthWorker, self).__init__()

    def run(self):
        QtCore.QThread.sleep(0.5)
        self.authenticate.emit()

class Worker(QtCore.QObject):
    finished = QtCore.pyqtSignal(str)
    authenticator = "n"

    def __init__(self, parent=None):
        super(Worker, self).__init__(parent)
        self.auth = AuthWorker()
        self.auth_thread = QtCore.QThread()
        self.auth.moveToThread(self.auth_thread)
        self.auth.authenticate.connect(self.setauthentication)
        self.auth_thread.started.connect(self.auth.run)

    def setauthentication(self):
        self.authenticator = "y"

    def run(self):
        self.auth_thread.start()
        QtCore.QThread.sleep(1)
        self.finished.emit('auth: %s' % self.authenticator)

class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.button = QtWidgets.QPushButton('Test', self)
        self.button.clicked.connect(self.handleButton)
        self.edit = QtWidgets.QLineEdit(self)
        self.edit.setReadOnly(True)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.edit)
        layout.addWidget(self.button)
        self.thread = QtCore.QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.thread)
        self.worker.finished.connect(self.handleFinished)
        self.thread.started.connect(self.worker.run)

    def handleFinished(self, text):
        self.thread.quit()
        self.edit.setText(text)

    def handleButton(self):
        if not self.thread.isRunning():
            self.edit.clear()
            self.thread.start()

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 100, 200, 100)
    window.show()
    sys.exit(app.exec_())

【讨论】:

  • 我认为这几乎解决了问题,但我如何从另一个窗口调用这些线程(一个按钮按下信号调用线程运行的 gui)
  • @Kermit。我扩展了我的代码示例以显示线程和简单 gui 之间的通信。
  • @ekhumoro 您将在哪里实现例如多处理并与主 GUI 通信?创建单独的类并通过 Qthread 从 Window 类调用它?还是在if __name__ == '__main__':下实现?后者避免包含在 GUI 的事件循环中)。 (顺便说一句:我可以想象这将是一个单独的问题..只要让我知道我会像这样将它与 ref 一起发布到这个 q)。
  • @ZF007 请开始一个新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多