2012-06-12 12 views
14

私は複数のスレッドを生成するPySide(Qt)GUIを持っています。スレッドはGUIを更新する必要があることがあります。私はこれを次のように解決しました:PySide:別のスレッドから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() 

    # ... 

もっと簡単な方法はありますか?シグナルやハンドラを作成してそれらを接続するには、数行のコードが必要です。

+0

なぜあなたは 'QThread'を使用していませんか? – Avaris

+0

もし 'QThread'で簡単なら、私は1つを使うことを考えます。問題は、既存のコードが 'threading.Thread'を使う傾向があることです。 – Petter

+1

'QThread'はシグナルをサポートしているので、より良いです。 'Signaller'クラスは必要ありません。しかし基本的に、あなたの方法は方法です。スレッドとGUIの間で通信するには、信号とスロットが必要です。 – Avaris

答えて

17

最近私はPySideでコーディングを開始しましたが、PyGObjectの同等の動作が必要でした(GLib.idle_add)。私はあなたの答え(https://stackoverflow.com/a/11005204/1524507)のコードに基づいていますが、これは自分でキューを使用する代わりにイベントを使用しています。

上記の回答リンクでも同じように使用されます。

+0

これは良いと思います。 – Petter

+0

これは素晴らしいことです。そして、PySideで動作させるために 'registerEventType'を' QEvent.Type'に再度ラップする小さな回避策でさえ目を開けました。ありがとう、コードを使用します。 – Trilarion

6

これまで私がこれまで持っていたことです。私はどこかにヘルパーモジュールに次のコードを書いた:

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) 

その後、私のスレッドは、非常に簡単にメインスレッドで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) 

私はこれがかなりいいと思います。

関連する問題