簡體   English   中英

PyQt 從非 QThread 喚醒主線程

[英]PyQt wake main thread from non-QThread

我有一個 PyQt 應用程序,它通過從不受我控制且不是QThread線程調用的回調接收來自外部源的信息。 將此類信息傳遞給主線程而不進行輪詢的正確方法是什么? 特別是,我想發出一個 Qt 信號,這樣我就可以在新數據到達時喚醒主線程(或另一個QThread )。

信號的默認連接類型是Qt.AutoConnection ,文檔是這樣描述的:

如果信號是從與接收對象不同的線程發出的,則信號將排隊,表現為 Qt::QueuedConnection。 否則,將直接調用插槽,表現為 Qt::DirectConnection。 連接類型是在發出信號時確定的。

因此,在發出信號之前,Qt 會在決定是否將其排隊之前簡單地比較發送方和接收方的當前線程關聯。 底層線程最初是如何啟動的並不重要。

這是一個使用 python 工作線程的簡單演示:

import sys, time, threading
from PyQt4 import QtCore, QtGui

class Worker(object):
    def __init__(self, callback):
        self._callback = callback
        self._thread = None

    def active(self):
        return self._thread is not None and self._thread.is_alive()

    def start(self):
        self._thread = threading.Thread(target=self.work, name='Worker')
        self._thread.start()

    def work(self):
        print('work: [%s]' % threading.current_thread().name)
        for x in range(5):
            time.sleep(1)
            self._callback(str(x))

class Window(QtGui.QPushButton):
    dataReceived = QtCore.pyqtSignal(str)

    def __init__(self):
        super(Window, self).__init__('Start')
        self.clicked.connect(self.start)
        self.dataReceived.connect(self.receive)
        self.worker = Worker(self.callback)

    def receive(self, data):
        print('received: %s [%s]' % (data, threading.current_thread().name))

    def callback(self, data):
        print('callback: %s [%s]' % (data, threading.current_thread().name))
        self.dataReceived.emit(data)

    def start(self):
        if self.worker.active():
            print('still active...')
        else:
            print('start: [%s]' % threading.current_thread().name)
            self.worker.start()

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    print('show: [%s]' % threading.current_thread().name)
    sys.exit(app.exec_())

典型輸出:

$ python test.py
show: [MainThread]
start: [MainThread]
work: [Worker]
callback: 0 [Worker]
received: 0 [MainThread]
still active...
callback: 1 [Worker]
received: 1 [MainThread]
still active...
callback: 2 [Worker]
received: 2 [MainThread]
still active...
callback: 3 [Worker]
received: 3 [MainThread]
callback: 4 [Worker]
received: 4 [MainThread]

如果您只是輪詢外部設備或庫,我會像處理它一樣處理它。 創建一個單獨的工作線程來處理回調,並向主 GUI 線程發出信號。

class Worker(QObject):

    data_ready = pyqtSignal(object, object)

    def callback(self, *args, **kwargs):
        self.data_ready.emit(args, kwargs)


class Window(...)

    def __init__(self):
        ...
        self.worker = Worker(self)
        # Connect worker callback function to your external library
        library.register_callback(self.worker.callback) #??
        ...

        # Mover worker to thread and connect signal
        self.thread = QThread(self)
        self.worker.data_ready.connect(self.handle_data)
        self.worker.moveToThread(self.thread)
        self.thread.start()

    @pyqtSlot(object, object)
    def handle_data(self, args, kwargs):
        # do something with data

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM