Динамическое обновление интерфейса
Есть программа, в которой необходимо сделать динамическое обновление интерфейса в ходе процесса работы приложения.
Есть ли у PyQt5 подобные инструменты?
Есть программа по обработке некоторых файлов. В ходе её процесса нужно выводить на экран статус выполнения и прочую доп. информацию.
Дело в том, что метод, который использую я, как мне кажется, не самый оптимальный и поэтому во время процесса программа подвисает (обновление не идёт).
Вот упрощённая версия программы. Да, тут ничего не виснет, но сам принцип сохранён.
from sys import argv, exit
import time
from PyQt5 import QtCore, QtWidgets, QtGui
from threading import Thread
# options
W_SIZE = (480, 360)
W_TITLE = "Template program"
W_ICON = ""
W_FIXEDSIZE = False
# класс данных
class MyProcessData:
def __init__(self):
self.num = 0
# класс для обработки
class MyProcessClass:
def process(self, update_function):
data = MyProcessData()
for i in range(1000):
data.num += 5
update_function(data)
time.sleep(0.0001)
# интерфейс
class GUI():
def __init__(self, window) -> None:
self.Title_Label = QtWidgets.QLabel(window)
self.Title_Label.setGeometry(QtCore.QRect(10, 10, 50, 20))
# Окно программы
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, wsize: tuple):
super().__init__()
self.setGeometry(250, 250, *wsize)
def setup(self, title, icon="", fixedsize=False):
self.setWindowTitle(title)
self.setWindowIcon(QtGui.QIcon(icon))
self.setFixedSize(self.geometry) if fixedsize else None
# класс всей программы
class Application:
def __init__(self) -> None:
self.qapp = QtWidgets.QApplication(argv)
self.window = MainWindow(W_SIZE)
self.ui = GUI(self.window)
def updateUI(self, data: MyProcessData):
self.ui.Title_Label.setText(str(data.num))
def start(self):
self.window.setup(W_TITLE, W_ICON, W_FIXEDSIZE)
self.connectUI()
process = MyProcessClass()
t = Thread(target=process.process, args=(self.updateUI,))
t.start()
self.window.show()
exit(self.qapp.exec_())
def connectUI(self):
pass
app = Application()
app.start()
Объясняю принцип работы
*Есть общий класс Application - это вся программа целиком, тут хранится всё.
MainWindow и GUI это всё окно программы, классы отвечают за интерфейс.
MyProcessClass и MyProcessData это классы обработчика, там проходят все вычисления.
По итогу создаётся объект класса MyProcessClass и вызывается функция process в новом потоке, в нее передается аргумент: функция, которая отвечает за обновление данных. Каждый новый цикл выполнения "обработки" информация на экране обновляется*
Ответы (1 шт):
Да, у PyQt5 подобные инструменты есть.
Например:
Класс QThread предоставляет независимый от платформы способ управления потоками.
Сигналы и слоты используются для связи между объектами. Механизм сигналов и слотов является центральной особенностью Qt и, вероятно, той частью, которая больше всего отличается от функций, предоставляемых другими фреймворками.
Попробуйте так:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *
# класс данных
class MyProcessData:
def __init__(self):
self.num = 0
# класс для обработки
class MyProcessClass(QThread):
stepChanged = pyqtSignal(int)
def __init__(self):
super().__init__()
myProcessData = MyProcessData()
self.data = myProcessData.num
def run(self):
for i in range(1000):
self.data += 5
self.stepChanged.emit(self.data)
self.msleep(50) # установите нужный вам интервал в мс.
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.centralwidget = QtWidgets.QWidget()
self.centralwidget.setObjectName("centralwidget")
self.setCentralWidget(self.centralwidget)
self.title_label = QtWidgets.QLabel()
self.title_label.setObjectName("title_label")
self.title_label.setStyleSheet('color: #B20600; font-size: 77px;')
self.pushButton = QtWidgets.QPushButton("Start")
self.pushButton.clicked.connect(self.btn_clicked)
layout = QGridLayout(self.centralwidget)
layout.addWidget(self.title_label, 0, 0, 2, 2, alignment=Qt.AlignCenter)
layout.addWidget(self.pushButton, 2, 1, alignment=Qt.AlignRight)
self.thread = None
def btn_clicked(self):
if self.thread is None:
self.thread = MyProcessClass()
self.thread.stepChanged.connect(self.onStepChanged)
self.thread.finished.connect(self.onFinished)
self.thread.start()
self.pushButton.setText("Stop")
else:
self.thread.terminate()
self.thread = None
self.pushButton.setText("Start")
def onStepChanged(self, data):
self.title_label.setNum(data)
def onFinished(self):
self.thread = None
self.pushButton.setText("Start")
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold))
w = MainWindow()
w.resize(480, 360)
w.show()
sys.exit(app.exec_())

