在标准 python 线程中发出信号 [英] Emit signal in standard python thread

查看:53
本文介绍了在标准 python 线程中发出信号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个线程应用程序,其中有一个网络线程.UI 部分将 callback 传递给该线程.该线程是普通 python 线程 - NO QThread.

I have a threaded application where I do have a network thread. The UI-part passes a callback to this thread. The thread is a normal python thread - it's NO QThread.

是否可以在此线程中发出 PyQT Slot?

Is it possible to emit PyQT Slot within this thread?

推荐答案

不,像这样从 python 线程发出 PyQt 信号是不可能的.

No, it is not possible to emit a PyQt signal from a python thread like this.

然而,一个可能的解决方案是使用共享的额外对象两个线程,进行必要的操作以最终发出线程安全PyQt 信号.

However, a possible solution is to use an additional object shared by both threads, making the necessary operations to finally emit a thread-safe PyQt signal.

这是一个SafeConnector"类的实现,使用了一对连接的套接字和队列在两个线程之间交换数据,并使用 QSocketNotifier 返回 Qt 的循环.QObject 用于使发出适当的 Qt 信号成为可能:

Here is an implementation of a "SafeConnector" class, making use of a pair of connected sockets and a Queue to exchange data between the two threads, and using a QSocketNotifier to get back in Qt's loop. A QObject is used to make it possible to emit a proper Qt signal:

from PyQt4 import Qt, QtCore, QtGui
import threading
import socket
import Queue
import time

# Object of this class has to be shared between
# the two threads (Python and Qt one).
# Qt thread calls 'connect',   
# Python thread calls 'emit'.
# The slot corresponding to the emitted signal
# will be called in Qt's thread.
class SafeConnector:
    def __init__(self):
        self._rsock, self._wsock = socket.socketpair()
        self._queue = Queue.Queue()
        self._qt_object = QtCore.QObject()
        self._notifier = QtCore.QSocketNotifier(self._rsock.fileno(),
                                                QtCore.QSocketNotifier.Read)
        self._notifier.activated.connect(self._recv)

    def connect(self, signal, receiver):
        QtCore.QObject.connect(self._qt_object, signal, receiver)

    # should be called by Python thread
    def emit(self, signal, args):
        self._queue.put((signal, args))
        self._wsock.send('!')

    # happens in Qt's main thread
    def _recv(self):
        self._rsock.recv(1)
        signal, args = self._queue.get()
        self._qt_object.emit(signal, args)

class PythonThread(threading.Thread):
    def __init__(self, connector, *args, **kwargs):
        threading.Thread.__init__(self, *args, **kwargs)
        self.connector = connector
        self.daemon = True

    def emit_signal(self):
        self.connector.emit(QtCore.SIGNAL("test"), str(time.time()))

    def run(self):
        while True:
            time.sleep(1)
            self.emit_signal()

if __name__ == '__main__':
    app = QtGui.QApplication([])
    mainwin = QtGui.QMainWindow()
    label = QtGui.QLabel(mainwin)
    mainwin.setCentralWidget(label)

    connector = SafeConnector()
    python_thread = PythonThread(connector)
    connector.connect(QtCore.SIGNAL("test"), label.setText)
    python_thread.start()

    mainwin.show()
    app.exec_()

这篇关于在标准 python 线程中发出信号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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