【问题标题】:PySide Signals not being sent to Slot, from QThread objectPySide 信号未从 QThread 对象发送到 Slot
【发布时间】:2018-03-21 19:38:16
【问题描述】:

我正在使用一个多线程应用程序,其中创建了一个工作线程,它发出一个信号。 创建线程后,我将信号与对象槽连接起来,这将执行一些操作。

问题是对象槽,没有被调用,有人可以帮忙弄清楚这段代码有什么问题吗?

import time
from PySide import QtCore
from PySide.QtCore import Slot, Signal


class Worker1(QtCore.QThread):

    task_done_signal = Signal(int)

    def __init__(self):
        super(Worker1, self).__init__()
        self._run = False

    def run(self):
        self._loop()

    def _loop(self):
        count = 0
        while self._run:
            print("running")
            count += 1
            self.task_done_signal.emit(count)

    def start(self):
        self._run = True
        super(Worker1, self).start()

    def stop(self):
        self._run = False


class Worker1Listener(QtCore.QObject):
    def __init__(self):
        super(Worker1Listener, self).__init__()

    @Slot()
    def print_task(self, val):
        print("listener: {}".format(val))


def test_signals_and_threads():

    # create the thread
    worker = Worker1()

    # create the listener
    listener = Worker1Listener()

    # connect the thread signal with the slot
    worker.task_done_signal.connect(listener.print_task)

    worker.start()

    time.sleep(5)

    worker.stop()

    time.sleep(5)


if __name__ == '__main__':
    test_signals_and_threads()

【问题讨论】:

  • 您没有运行事件循环。

标签: python multithreading pyside qt-signals qt-slot


【解决方案1】:

您的代码有几个错误:

  • 您必须有一个事件循环,以便 Qt 处理应用程序的各个对象之间的通信,在您的情况下,您必须使用 QCoreApplication

  • 装饰器Slot 必须将函数参数的数据类型作为参数,在您的情况下:Slot(int)

  • 你不应该使用 time.sleep,因为它是阻塞的并且不会让事件循环完成它的工作,一个可能的解决方案是在 QTimer 旁边使用 QEventLoop

    李>
  • 始终建议留出较短的时间进行交流,为此我们使用QThread.msleep

  • 在不同线程中的信号之间进行连接时,正确的选项是使用Qt.QueuedConnection 选项。


import sys

from PySide import QtCore

class Worker1(QtCore.QThread):
    task_done_signal = QtCore.Signal(int)

    def __init__(self):
        super(Worker1, self).__init__()
        self._run = False

    def run(self):
        self._loop()

    def _loop(self):
        count = 0
        while self._run:
            print("running")
            count += 1
            self.task_done_signal.emit(count)
            QtCore.QThread.msleep(1)

    def start(self):
        self._run = True
        super(Worker1, self).start()

    def stop(self):
        self._run = False


class Worker1Listener(QtCore.QObject):
    @QtCore.Slot(int)
    def print_task(self, val):
        print("listener: {}".format(val))

def test_signals_and_threads():
    app = QtCore.QCoreApplication(sys.argv)
    # create the thread
    worker = Worker1()
    # create the listener
    listener = Worker1Listener()

    # connect the thread signal with the slot
    worker.task_done_signal.connect(listener.print_task, QtCore.Qt.QueuedConnection)

    worker.start()

    loop = QtCore.QEventLoop()
    QtCore.QTimer.singleShot(5000, loop.quit)
    loop.exec_()

    worker.stop()

    loop = QtCore.QEventLoop()
    QtCore.QTimer.singleShot(5000, loop.quit)
    loop.exec_()

    #sys.exit(app.exec_())

if __name__ == '__main__':
    test_signals_and_threads()

【讨论】:

  • 我已经阅读并阅读,创建了一个“app = QtCore.QCoreApplication(sys.argv)”,但永远无法达到您的解决方案,感谢@eyllanesc !!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-11
  • 2018-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多