The problem has nothing to do with the use of QThread or not. The problem is that the GUI elements (for example the QWidget, QTextDocument, etc) are not thread-safe so you should not modify them or create them in a different thread than the main one. To emphasize my initial comment in my solution I will not use QThread but I will continue using threading but I will send the information to the main thread through signals(what if they are thread-safe):
import sys, time
from threading import Thread
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QWidget,
QPlainTextEdit,
QHBoxLayout,
)
class Worker(QObject):
messageChanged = pyqtSignal(str)
def start(self, fn):
Thread(target=self._execute, args=(fn,), daemon=True).start()
def _execute(self, fn):
fn(self)
def write(self, message):
self.messageChanged.emit(message)
def run1(worker):
for i in range(20):
worker.write(f"{i}\n")
time.sleep(0.0125)
def run2(worker):
for i in range(20):
worker.write(f"{i}\n")
time.sleep(0.0125)
def run3(worker):
for i in range(20):
worker.write(f"{i}\n")
time.sleep(0.0125)
app = QApplication([sys.argv])
win = QMainWindow()
text_1 = QPlainTextEdit()
text_2 = QPlainTextEdit()
text_3 = QPlainTextEdit()
my_widget = QWidget()
my_widget.layout = QHBoxLayout()
my_widget.layout.addWidget(text_1)
my_widget.layout.addWidget(text_2)
my_widget.layout.addWidget(text_3)
my_widget.setLayout(my_widget.layout)
win.setCentralWidget(my_widget)
worker1 = Worker()
worker1.messageChanged.connect(text_1.appendPlainText)
worker2 = Worker()
worker2.messageChanged.connect(text_2.appendPlainText)
worker3 = Worker()
worker3.messageChanged.connect(text_3.appendPlainText)
worker1.start(run1)
worker2.start(run2)
worker3.start(run3)
win.show()
sys.exit(app.exec_())
CLICK HERE to find out more related problems solutions.