Потоки и сигналы
Имеется следующий код:
import time
import sys
#from PyQt6.QtWidgets import (
from PyQt5.QtWidgets import (
QApplication,
QPushButton,
QTextEdit,
QVBoxLayout,
QWidget
)
from threading import Thread
class Window(QWidget):
def __init__(self):
super().__init__()
mainLayout = QVBoxLayout()
self.output = QTextEdit()
self.output.setReadOnly(True)
mainLayout.addWidget(self.output)
self.startButton = QPushButton("Start")
self.startButton.clicked.connect(self.start)
mainLayout.addWidget(self.startButton)
self.setLayout(mainLayout)
def task(self):
while True:
obj = Actions()
obj.do()
time.sleep(3)
def start(self):
t1 = Thread(target=self.task)
t1.start()
class Actions():
def do(self):
window.output.append("...")
if __name__ == "__main__":
app = QApplication([])
window = Window()
window.show()
sys.exit(app.exec())
При выполнении данного примера (для PyQt5) получаю предупреждение cледующего плана:
QObject::connect: Cannot queue arguments of type 'QTextCursor' (Make sure 'QTextCursor' is registered using qRegisterMetaType().)
- нельзя взаимодействовать с виджетами в других потоках, поэтому этот варнинг и выводится
- когда потоку надо что-то поменять в окне, он отправляет сигнал главному потоку, а обработчик в главном потоке выполняет необходимые изменения
Как реализовать второй пункт? Есть ли хорошие туториалы с примерами по этой теме?
Заранее спасибо!
Ответы (1 шт):
Автор решения: S. Nick
→ Ссылка
Вам не нужны дополнительные библиотеки для организации работы с потоками.
Читаем Signals & Slots
Смотрим 3 разных и простых способа работы с потоками.
import sys
#import time
#from threading import Thread
#from PyQt6.QtWidgets import (
from PyQt5.QtWidgets import ( QApplication, QPushButton,
QTextEdit, QVBoxLayout, QWidget)
from PyQt5.QtCore import QThread, pyqtSignal # +++
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
class Thread(QThread):
dateSignal = pyqtSignal(str) # +++
def __init__(self):
super().__init__()
self.num = 1
def run(self):
while True:
# тут вы выполняете какие-то длительные действия
text = f'... {self.num}'
# тут вы испускаете сигнал и передаете какие-то данные
self.dateSignal.emit(text) # +++
# 2000 мс
self.msleep(2000)
self.num += 1
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class Window(QWidget):
def __init__(self):
super().__init__()
self.output = QTextEdit()
self.output.setReadOnly(True)
self.startButton = QPushButton("Start")
self.startButton.clicked.connect(self.start)
mainLayout = QVBoxLayout(self)
mainLayout.addWidget(self.output)
mainLayout.addWidget(self.startButton)
self.thread = Thread() # +++
self.thread.dateSignal.connect(self.update_data) # +++
def start(self):
#- t1 = Thread(target=self.task)
#- t1.start()
self.thread.start() # +++
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
def update_data (self, text): # +++
self.output.append(text)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'''
def task(self):
while True:
obj = Actions()
obj.do()
time.sleep(3)
def start(self):
t1 = Thread(target=self.task)
t1.start()
class Actions():
def do(self):
window.output.append("...")
'''
if __name__ == "__main__":
app = QApplication([])
window = Window()
window.show()
sys.exit(app.exec())
