Как правильно показать в основном окне результат счетчика цикла, который выполняется в дополнительном потоке?
Прошу помощи. Есть класс Example(), в котором выполняется определенная работа с файлами на ПК в цикле продолжительное время.
Есть класс окна MainWindow() PyQt в другом модуле. В окне я выбираю пути, кое-какие опции и уже с ними нажимаю на кнопку и запускаю этот цикл.
Вопрос: чтобы отслеживать работу программу мне нужно отображать счетчик циклов, который работает в другом модуле/классе, как это сделать?
Минимально воспроизводимый пример:
import sys
import time
from PyQt6.QtCore import pyqtSignal, Qt, QThread
from PyQt6.QtWidgets import QApplication,QWidget, QGridLayout, QPushButton, QLabel
class Example(QThread):
file_processed = pyqtSignal()
def run(self):
for i in range(5):
self.file_processed.emit()
print('Прошёл операцию')
time.sleep(3)
class MainWindow(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.file_processor = Example()
self.setWindowTitle('Создатель актов')
self.setGeometry(1000, 400, 500, 150)
self.counter = 0
layout = QGridLayout()
self.setLayout(layout)
# Кнопка запуска
start_btn = QPushButton("Начать создание")
start_btn.setCheckable(True)
start_btn.clicked.connect(self.the_button_was_clicked)
layout.addWidget(start_btn, 3, 1)
# Строка состояния
self.acts_counter = QLabel('0')
layout.addWidget(self.acts_counter, 4, 1, alignment=Qt.AlignmentFlag.AlignCenter)
self.file_processor.file_processed.connect(self.update_counter)
self.show()
def update_counter(self):
self.counter += 1
print(self.counter)
self.acts_counter.setText(str(self.counter))
def the_button_was_clicked(self):
self.acts_counter.setText('0')
self.counter = 0
self.file_processor.run()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())
Нужно чтобы self.acts_counter менялась во время выполнения цикла run класса Example. В этом коде она меняется только когда цикл останавливается.
Ответы (1 шт):
Класс QThread предоставляет независимый от платформы способ управления потоками.
void QThread::start(QThread::Priority priority = InheritPriority)
Начинает выполнение потока вызовом run().
void QThread::run()
Начальная точка потока. После вызова
start()вновь созданный поток вызывает эту функцию. Реализация по умолчанию просто вызывает exec(). Вы можете переопределить эту функцию, чтобы облегчить расширенное управление потоками. Возврат из этого метода завершит выполнение потока.
import sys
#import time
'''
from PyQt6.QtCore import pyqtSignal, Qt, QThread
from PyQt6.QtWidgets import QApplication, QWidget, QGridLayout, QPushButton, QLabel
'''
from PyQt5.QtCore import pyqtSignal, Qt, QThread
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QPushButton, QLabel
from PyQt5.QtGui import QFont # +++
class Thread(QThread):
# ----------------------------> vvv <---------------------------------------
file_processed = pyqtSignal(int)
def run(self):
# -------------------> vvvv <-----------------------------------------------
for i in range(1, 6):
# ---------------------------------> v <------------------------------------
self.file_processed.emit(i)
# print('Прошёл операцию')
# time.sleep(3)
self.msleep(1000)
class MainWindow(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setWindowTitle('Создатель актов')
# self.setGeometry(1000, 400, 500, 150)
self.resize(500, 150)
# self.counter = 0
layout = QGridLayout()
self.setLayout(layout)
# Кнопка запуска
# ----> vvvvv <------------------------------------------------------------
self.start_btn = QPushButton("Начать создание")
self.start_btn.setCheckable(True)
self.start_btn.clicked.connect(self.the_button_was_clicked)
layout.addWidget(self.start_btn, 3, 1)
# Строка состояния
self.acts_counter = QLabel()
layout.addWidget(self.acts_counter, 4, 1, alignment=Qt.AlignmentFlag.AlignCenter)
self.file_processor = Thread()
self.file_processor.file_processed.connect(self.update_counter)
self.file_processor.finished.connect(
lambda: self.start_btn.setEnabled(True),
)
# self.show()
# -------------------------> vvvvv <---------------------------------------
def update_counter(self, value):
# self.counter += 1
# print(self.counter)
# self.acts_counter.setText(str(self.counter))
self.acts_counter.setNum(value)
def the_button_was_clicked(self):
self.acts_counter.setText('0')
# self.counter = 0
# self.file_processor.run()
# ------------------------> vvvvvvv <---------------------------------------
self.file_processor.start() # !!! +++
self.start_btn.setEnabled(False)
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setFont(QFont("Times", 12, QFont.Bold))
window = MainWindow()
window.show()
sys.exit(app.exec())

