pyqt5 - не работают методы addWidget и addLayout в отдельных потоках
Такое происходит, например, при попытке добавить QLabel в QVBoxLayout в отдельном потоке. Вот демонстрация:
import sys
from threading import Thread
from PyQt5.QtWidgets import QVBoxLayout, QLabel, QWidget, QApplication
class Ui(QWidget):
def __init__(self):
QWidget.__init__(self)
self.resize(300, 200)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.layout.addWidget(QLabel(text="hello"))
# Тут попытка добавить QLabel в отдельном потоке
Thread(target=self.add_label).start()
def add_label(self):
self.layout.addWidget(QLabel(text="new label"))
app = QApplication(sys.argv)
ui = Ui()
ui.show()
sys.exit(app.exec_())
В результате в QVBoxLayout будет присутствовать исключительно один QLabel, который был добавлен в конструкторе:
Какие существуют методы борьбы с этим? Это какая-то ошибка?
Ответы (2 шт):
Автор решения: Zemf4you
→ Ссылка
Благодаря комментарию Alexander Chernin смог решить проблему с помощью PyqtSignal.
Пример:
import sys
from threading import Thread
from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtWidgets import QVBoxLayout, QLabel, QWidget, QApplication
class Communicate(QObject):
customEvent = pyqtSignal()
class Ui(QWidget):
def __init__(self):
QWidget.__init__(self)
self.resize(300, 200)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.com = Communicate()
self.com.customEvent.connect(self.add_label)
self.layout.addWidget(QLabel(text="hello"))
Thread(target=self.other_thread).start()
def other_thread(self):
self.com.customEvent.emit()
def add_label(self):
self.layout.addWidget(QLabel(text="new label"))
app = QApplication(sys.argv)
ui = Ui()
ui.show()
sys.exit(app.exec_())
Автор решения: S. Nick
→ Ссылка
Обычно, это может выглядеть так:
import sys
#from threading import Thread
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtWidgets import QVBoxLayout, QLabel, QWidget, QApplication
class MyThread(QtCore.QThread):
mysignal = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
QtCore.QThread.__init__(self, parent)
def run(self):
for i in range(2):
self.msleep(1000)
text = "Hello World"
#Передача данных из потока через сигнал
self.mysignal.emit(f"{text} {i}")
class Ui(QWidget):
def __init__(self):
super().__init__()
self.resize(300, 200)
self.label = QLabel(text="hello")
self.layout = QVBoxLayout(self)
self.layout.addWidget(self.label)
# Тут попытка добавить QLabel в отдельном потоке
# Thread(target=self.add_label).start()
self.mythread = MyThread()
self.mythread.mysignal.connect(self.add_label)
self.mythread.start()
def add_label(self, text):
self.layout.addWidget(QLabel(text))
if __name__ == '__main__':
app = QApplication(sys.argv)
ui = Ui()
ui.show()
sys.exit(app.exec_())

