2016-05-11 45 views
1

コードは実行されますが、エラー:QObject::setParent: Cannot set parent, new parent is in a different threadが表示されます。QThreadからウィジェットのメソッドを呼び出す方法

何が原因である可能性がありますか?我々は信号を使用してウィジェットの方法に到達して(代わりにスレッドから直接呼び出しの)スロット機構れる下に掲載した例では

enter image description here

import Queue, threading 
from PyQt4 import QtGui, QtCore 
app = QtGui.QApplication([])  

class MessageBox(QtGui.QMessageBox): 
    def __init__(self, parent=None): 
     QtGui.QMessageBox.__init__(self, parent)  

    def showMessage(self): 
     self.setText('Completed') 
     self.show() 

class Thread(QtCore.QThread): 
    def __init__(self, queue, parent=None): 
     QtCore.QThread.__init__(self, parent)  
     self.queue=queue   

    def run(self):  
     while True: 
      number=self.queue.get() 
      result = self.process(number) 
      messagebox.showMessage() 
      self.queue.task_done() 

    def process(self, number): 
     timer = QtCore.QTimer() 
     for i in range(number): 
      print 'processing: %s'%i 
      QtCore.QThread.sleep(1)   
     return True  

messagebox = MessageBox() 

queue = Queue.Queue() 
thread = Thread(queue) 
thread.start() 

lock=threading.Lock() 
lock.acquire() 
queue.put(3) 
lock.release()  
app.exec_() 

。コードの実行は期待通りに機能します。私が解決策を知っている間でも、なぜそれが起こっているのか知りたいです。

class Emitter(QtCore.QObject): 
    signal = QtCore.pyqtSignal() 

class MessageBox(QtGui.QMessageBox): 
    def __init__(self, parent=None): 
     QtGui.QMessageBox.__init__(self, parent)  

    def showMessage(self): 
     self.setText('Completed') 
     self.show() 

class Thread(QtCore.QThread): 
    def __init__(self, queue, parent=None): 
     QtCore.QThread.__init__(self, parent)  
     self.queue=queue   

    def run(self): 
     emitter = Emitter() 
     emitter.signal.connect(messagebox.showMessage) 

     while True: 
      number=self.queue.get() 
      result = self.process(number) 
      emitter.signal.emit() 
      self.queue.task_done() 

    def process(self, number): 
     timer = QtCore.QTimer() 
     for i in range(number): 
      print 'processing: %s'%i 
      QtCore.QThread.sleep(1)   
     return True 

messagebox = MessageBox() 

queue = Queue.Queue() 
thread = Thread(queue) 
thread.start() 

lock=threading.Lock() 
lock.acquire() 
queue.put(3) 
lock.release() 

app.exec_() 
+2

エラーメッセージは完全に記述的です。オブジェクトを別のオブジェクトに置き換えようとしていますが、もう一方は別のスレッドに存在しています。それをしないでください。 –

答えて

2

あなたは2つのことをする必要があります。エミッタオブジェクトを2番目のスレッドに移動する必要があり、showMessageをスロットとして宣言する必要があります。

emitter = Emitter() 
emitter.moveToThread(self) 
@QtCore.pyqtSlot() 
def showMessage(self): 
    ... 

しかし、それは、QThreads継承をエミッタを作成し、メインスレッドにシグナルとスロットを接続し、

emitter = Emitter() 
emitter.signal.connect(messagebox.showMessage) 
emitter.moveToThread(thread) 

また第二のスレッドに移動し、おそらく良いでしょうQObjectから、エミッタオブジェクトが絶対に必要なわけではないので、シグナルを直接QThreadに置くことができます。 QThreadがメインスレッドに実際に存在し、スロットにあるスロット(runを除く)がメインスレッドで実行されることに注意してください。言われていること

あなたがメインと第二のスレッド間を行き来するデータを送信する場合、あなたはQtの中でQThread年代を使用してのワーカーパターンに見てみたいことがあります。

+0

'run'の中から呼び出される関数やメソッドは、' run'スレッドと同じように実行されます。 'emitter.moveToThread(thread)'の違いによって明らかになりません。それがサンプルコードにどのように実装されているか見ることは興味深いでしょう。 – alphanumeric

関連する問題