how to clear QTextEdit in different thread in pyQt4

multithreading, pyqt4, python

Solution

One of the main gotcha's about Qt is that you cannot call any QWidget methods from any thread other than the main GUI thread. All of your communication must be done by emitting signals from the extra threads, which will forward to the main gui.

To start, I see you are using globals, and a lack of the `self` keyword, so I assume you are not using classes. My example will incorporate a class example as well.

This is example is bare bones, just like yours, outlining the direction you might want to take:

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)

The main thing to notice is that the functions running in the thread are emitting signals. They have no knowledge of the QWidgets in the other classes. Your `MyWidget` class connects the signal to a slot that can update the QLineEdit. When the thread emits a signal, it will be queued into the main thread and executed by the receiving slot.

I also created a simple QThread subclass that can take a function and args, replicating the way the standard lib Thread class works. You should stick to using QThread because it is a QObject subclass, and supports signals and can run an event loop.

Problem

I have a QTextEdit component created in the "main" thread of my program then I start another thread, which will be updating this QTextEdit every x seconds, but then I get this error: ``` QObject: Cannot create children for a parent that is in a different thread. ``` this is the way I'm doing it: ``` 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 ``` this two last lines of code give me the above mentioned error. Can someone give me a clue on how to handle this? thanks!

Original source