PyQt5 изменение QTextBrowser в QThread
При попытке изменить текст в QTextBrowser из потока QThread программа просто вылетает, а текст ошибки Qt не пишет.
Нужно каждую секунду менять текст и чтобы окно не висло.
Если заменить TextBrowser на прогресс бар - то всё работает нормально. Так как это исправить?
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QThread
import sys
import time
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.tb = QTextBrowser(self)
self.tb.setGeometry(30, 30, 100, 100)
self.btn = QPushButton('Start', self)
self.btn.move(50, 150)
self.setGeometry(300, 300, 200, 200)
self.setWindowTitle("Python")
self.dt = DrawThread(self)
self.btn.clicked.connect(self.doAction)
def doAction(self):
self.dt.start()
class DrawThread(QThread):
def __init__(self, mainwindow, parent=None):
super().__init__()
self.mw = mainwindow
self.mw.tb.setText("123") # Тут всё работает
def run(self):
for i in range(100):
time.sleep(1)
self.mw.tb.setText(str(i)) # Здесь вылетает
if __name__ == '__main__':
App = QApplication(sys.argv)
window = Example()
window.show()
sys.exit(App.exec())```
Ответы (2 шт):
Управлять ui в qt можно только из главного треда. Чтоб решить эту задачу создай слот с параметром текста в главном потоке. В дополнительном потоке создай сигнал. Доп поток эмитит сигнал, а слот приняв его делает setText.
Все взаимодействия между объектами в разных тредах просто так не выполняются. У меня питон выдавал ошибку перед падением)
Нельзя обращаться из дополнительного потока к виджетам основного окна! Надо использовать сигналы и слоты, но в вашем случае дополнительный поток вообще не нужен.
Вам достаточно использовать QTimer.
import sys
#import time
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QWidget, QApplication, \
QTextBrowser, QPushButton, QVBoxLayout
class Example(QWidget):
def __init__(self):
super().__init__()
self.i = 0
self.tb = QTextBrowser()
self.tb.setText('Hello World')
self.btn = QPushButton('Start')
self.btn.clicked.connect(self.doAction)
layout = QVBoxLayout(self)
layout.addWidget(self.tb)
layout.addWidget(self.btn)
self.timer = QTimer() # +++
self.timer.setInterval(1000) # Миллисекунды # +++
self.timer.timeout.connect(self.updateTime) # +++
def doAction(self):
if self.btn.text() == 'Start':
self.timer.start()
self.btn.setText('Stop')
else:
self.timer.stop()
self.btn.setText('Start')
def updateTime(self): # +++
self.tb.setText(f'{self.i}')
self.i += 1
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Example()
window.setWindowTitle("Python")
window.show()
sys.exit(app.exec_())
