Pet*_*ter 15 python qt multithreading signals-slots pyside
我有一个PySide(Qt)GUI,它产生多个线程.线程有时需要更新GUI.我通过以下方式解决了这个问题:
class Signaller(QtCore.QObject) :
    my_signal = QtCore.Signal(QListWidgetItem, QIcon)
signaller = Signaller()
class MyThread(threading.Thread):
    def __init__(self):
        super(IconThread, self).__init__()
        # ...
    def run(self) :
        # ...
        # Need to update the GUI
        signaller.my_signal.emit(self.item, icon)
#
# MAIN WINDOW        
# 
class Main(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        # ...
        # Connect signals
        signaller.my_signal.connect(self.my_handler)
    @QtCore.Slot(QListWidgetItem, QIcon)
    def my_handler(self, item, icon):
        item.setIcon(icon)
    def do_something(self, address):
        # ...
        # Start new thread 
        my_thread = MyThread(newItem)
        my_thread.start()
    # ...
Run Code Online (Sandbox Code Playgroud)
有没有更简单的方法?创建信号,处理程序和连接它们需要几行代码.
chf*_*foo 19
我最近开始使用PySide进行编码,我需要等效的PyGObject GLib.idle_add行为.我根据您的答案(/sf/answers/770364311/)编写代码,但是这个代码使用事件而不是自己使用队列.
from PySide import QtCore
class InvokeEvent(QtCore.QEvent):
    EVENT_TYPE = QtCore.QEvent.Type(QtCore.QEvent.registerEventType())
    def __init__(self, fn, *args, **kwargs):
        QtCore.QEvent.__init__(self, InvokeEvent.EVENT_TYPE)
        self.fn = fn
        self.args = args
        self.kwargs = kwargs
class Invoker(QtCore.QObject):
    def event(self, event):
        event.fn(*event.args, **event.kwargs)
        return True
_invoker = Invoker()
def invoke_in_main_thread(fn, *args, **kwargs):
    QtCore.QCoreApplication.postEvent(_invoker,
        InvokeEvent(fn, *args, **kwargs))
Run Code Online (Sandbox Code Playgroud)
在上面的答案链接中使用相同的方法.
这就是我到目前为止所拥有的.我在辅助模块中的某处编写了以下代码:
from Queue import Queue
class Invoker(QObject):
    def __init__(self):
        super(Invoker, self).__init__()
        self.queue = Queue()
    def invoke(self, func, *args):
        f = lambda: func(*args)
        self.queue.put(f)
        QMetaObject.invokeMethod(self, "handler", QtCore.Qt.QueuedConnection)
    @Slot()
    def handler(self):
        f = self.queue.get()
        f()
invoker = Invoker()
def invoke_in_main_thread(func, *args):
    invoker.invoke(func,*args)
Run Code Online (Sandbox Code Playgroud)
然后我的线程可以非常轻松地运行代码来更新主线程中的GUI.无需为每个操作创建和连接信号.
class MyThread(threading.Thread):
    def __init__(self):
        super(IconThread, self).__init__()
        # ...
    def run(self) :
        # ...
        # Need to update the GUI
        invoke_in_main_thread(self.item.setIcon, icon)
Run Code Online (Sandbox Code Playgroud)
我认为这样的事情非常好.