3

プログラムの「メイン」スレッドでQTextEditコンポーネントを作成し、別のスレッドを開始します。このスレッドはx秒ごとにこのQTextEditを更新しますが、次のエラーが発生します。

QObject: Cannot create children for a parent that is in a different thread.

これは私がそれをしている方法です:

def initGui():
   #some gui components
   global txt_list

   txt_list = QtGui.QTextEdit(w)
   txt_list.resize(580,400)
   txt_list.move(50, 50)
   txt_list.setReadOnly(1)
   txt_list.setFont(font_consolas)
   #more gui components

def update_list():
   t_monitor = threading.Thread(target=monitor_vector)
   t_monitor.daemon = True
   t_monitor.setName('monitor')
   t_monitor.start()

def monitor_vector():
   #retrieve info...
   lock = threading.Lock
   lock = True
   txt_list.clear() #clear list, to set the new one
   txt_list.setText('updated list')
   lock = False

この最後の2行のコードは、上記のエラーを示しています。誰かが私にこれを処理する方法の手がかりを与えることができますか?

ありがとう!

4

1 に答える 1

7

Qtに関する主な落とし穴の1つは、メインGUIスレッド以外のスレッドからQWidgetメソッドを呼び出すことができないことです。すべての通信は、メインのGUIに転送される追加のスレッドから信号を送信することによって行われる必要があります。

まず、グローバルを使用していて、selfキーワードがないので、クラスを使用していないと思います。私の例には、クラスの例も組み込まれます。

これは、あなたと同じように、あなたが取りたいと思うかもしれない方向を概説する、必要最低限​​の例です。

from PyQt4 import QtGui, QtCore

class MyWidget(QtGui.QWidget):

    def __init__(self, parent=None):
        super(MyWidget, self).__init__(parent)

        ...
        self.txt_list = QtGui.QTextEdit(self)
        self.txt_list.resize(580,400)
        self.txt_list.move(50, 50)
        self.txt_list.setReadOnly(1)
        self.txt_list.setFont(font_consolas)
        ...
        self.monitor = Monitor()
        self.monitor.updateText.connect(self._handleTextUpdate)
        self.monitor.update_list()

    def _handleTextUpdate(self, txt):
        self.txt_list.clear()
        self.txt_list.setText(txt)


class Monitor(QtCore.QObject):

    updateText = QtCore.pyqtSignal(str)

    def update_list(self):
        t_monitor = Thread(self.monitor_vector, parent=self)
        t_monitor.daemon = True
        t_monitor.setName('monitor')
        t_monitor.start()

    def monitor_vector(self):
        ...
        self.updateText.emit('updated list')


class Thread(QtCore.QThread):

    def __init__(self, fn, args, kwargs, parent=None):
        super(Thread, self).__init__(parent)
        self._fn = fn 
        self._args = args 
        self._kwargs = kwargs 

    def run(self):
        self._fn(*self._args, **self._kwargs)

注意すべき主な点は、スレッドで実行されている関数が信号を出力していることです。彼らは他のクラスのQWidgetsについての知識を持っていません。クラスは、信号をQLineEditMyWidgetを更新できるスロットに接続します。スレッドがシグナルを発信すると、メインスレッドのキューに入れられ、受信スロットによって実行されます。

また、関数と引数を受け取ることができる単純なQThreadサブクラスを作成し、標準のlibThreadクラスの動作を複製しました。QThreadはQObjectサブクラスであり、シグナルをサポートし、イベントループを実行できるため、QThreadの使用に固執する必要があります。

于 2012-08-28T06:01:09.227 に答える