Реализация прогресса QProgressBar одного скрипта в окне второго
Описание: из окна приложения (скрипт m1.py), по кнопке, вызывается скрипт (otv.py), который отрабатывает в фоновом режиме. Процесс выполнения второго скрипта отображается в statusBar первого приложения.
На данный момент функционал реализован через третий скрипт (b1.py).
Вопрос: Как корректно передать сигнал процесса выполнения ProgressBar из второго скрипта otv.py, первому m1.py минуя третий.
P.S. В один скрипт просьба не объединять, поскольку пример схематичный и скриптов типа otv.py несколько, а m1.py перегружен.
m1.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
from PyQt5.QtCore import (QDate, QObject, QEvent, pyqtSlot, pyqtSignal, QThread,
QTimeLine, QTimer, QSize, QSettings, QBasicTimer)
class Thread(QtCore.QThread):
progress_chek = pyqtSignal(int)
finished = pyqtSignal()
def __init__(self):
super().__init__()
self.x = 0
def run(self):
print('m1.py > class Thread > def run >')
while self.x <= 200:
try:
self.progress_chek.emit(self.x)
except Exception as exc_emit:
print('m1.py > class Thread > ошибка exc_emit = ', exc_emit)
self.x += 10
self.msleep(400)
print()
print('m1.py > class Thread > def run > x2 =', self.x)
print('m1.py > class Thread > self.finished.emit()')
self.finished.emit()
class Example(QtWidgets.QMainWindow):
def __init__(self):
super(Example, self).__init__()
QtWidgets.QMainWindow.__init__(self)
self.initUI(self)
def initUI(self, QProgressBar):
self.btn_dir = QtWidgets.QPushButton('Запуск')
self.btn_dir.clicked.connect(self.ot)
# btn_dir.clicked.connect(self.ot_v)
self.progress = QtWidgets.QProgressBar(self, minimum=0, maximum=100)
self.progress.setObjectName("progress")
self.progress.setStyleSheet('text-align: center; '
'min-height: 15px; max-height: 15px;')
self.thread = Thread()
try:
self.thread.progress_chek.connect(self.update_progressbar)
self.thread.finished.connect(self.finished_progressbar)
except Exception as exc_t:
print('m1.py > class Example > ошибка exc_t = ', exc_t)
self.progressbar_self()
self.statusBar().insertPermanentWidget(1, self.progress)
self.statusBar().addPermanentWidget(self.btn_dir)
def ot(self):
print('m1.py > class Example > def ot > ')
import otv
def progressbar_self(self):
print('m1.py > class Example > def progressbar_self > ')
import b1
b1.self = self
def progressbar_reset(self):
print('m1.py > class Example > def progressbar_reset > ')
self.progress.reset()
def signal(self, value):
print('m1.py > class Example > def signal > ')
print(f'прогресс процесса {value} %')
self.progress.setValue(value)
def update_progressbar(self, val):
print('m1.py > class Example > def update_progressbar > ')
try:
self.progress.setValue(val)
except Exception as exc_val:
print('m1.py > class Example > ошибка exc_val = ', exc_val)
def finished_progressbar(self):
print()
print('m1.py > class Example > def finished_progressbar > ')
self.label.clear()
msg = QtWidgets.QMessageBox.information(
self,
'ВНИМАНИЕ',
'Процесс завершен - можете закрывать окно!'
)
self.progress.reset()
def ot_v(self):
print('m1.py > class Example > def ot_v > ')
try:
self.thread.x = 0
self.progress.reset()
self.progress.setValue(0)
self.thread.start()
except Exception as thread:
print('m1.py > class Example > ошибка thread = ', thread)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = Example()
ex.show()
ex.resize(500, 300)
sys.exit(app.exec())
otv.py
import time
from m1 import Example
from b1 import self
print()
print('_______________________________________________________')
print()
def widg_gotov():
time.sleep(5.0)
print('otv > обнулить ProgressBar')
Example.progressbar_reset(self)
def while_x(x):
while x < 200:
x = x+10
time.sleep(0.4)
print('otv > def while_x > x1 =', x)
try:
Example.ot_v(self)
except Exception as exc_ot:
print('otv > ошибка exc_ot = ', exc_ot)
x = 0
while_x(x)
print()
widg_gotov()
print('_______________________________________________________')
b1.py
self = []
if __name__ == '__main__':
print()
Ответы (2 шт):
Я понял так, что с Реализацией QProgressBar в потоке вы уже разобрались.
Теперь вы хотите понять как взаимодействовать с QProgressBar
в основном потоке, но сам QProgressBar находится в одном модуле,
а какой-то цикл с изменяемыми данными в другом модуле.
Совсем не понятно для чего вам модуль b1.py ?
Нельзя использовать time.sleep(...) в основном потоке - это
замораживает интерфейс.
Вам надо познакомиться с QTimer.
Класс QTimer предоставляет повторяющиеся и однократные таймеры.
m1.py
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
from PyQt5.QtCore import (QDate, QObject, QEvent, pyqtSlot,
pyqtSignal, QThread, QTimeLine, QTimer, QSize, QSettings,
QBasicTimer)
# ??? import b1
from otv import OtvClass
class Example(QtWidgets.QMainWindow):
def __init__(self):
super(Example, self).__init__()
# self.initUI(self)
self.initUI()
# def initUI(self, QProgressBar):
def initUI(self):
self.btn_dir = QtWidgets.QPushButton('Запуск')
self.btn_dir.clicked.connect(self.ot)
# btn_dir.clicked.connect(self.ot_v)
self.progress = QtWidgets.QProgressBar(self, minimum=0, maximum=100)
self.progress.setObjectName("progress")
self.progress.setStyleSheet('text-align: center; '
'min-height: 15px; max-height: 15px;')
self.progress.setRange(0, 200) # +++
self.statusBar().insertPermanentWidget(1, self.progress)
self.statusBar().addPermanentWidget(self.btn_dir)
def ot(self):
print('m1.py > class Example > def ot > ')
# ??? import otv
self.otvClass = OtvClass(self) # +++
self.btn_dir.setEnabled(False) # +++
self.otvClass.timer.start() # +++
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = Example()
ex.show()
ex.resize(500, 300)
sys.exit(app.exec())
otv.py
# ??? import time
# ??? from m1 import Example
# ??? from b1 import self
from PyQt5.Qt import *
class OtvClass(QObject):
x = 0
def __init__(self, parent=None):
super(OtvClass, self).__init__(parent)
self.parent = parent
self.timer = QTimer()
self.timer.setInterval(400)
self.timer.timeout.connect(self.while_x)
# def while_x(self, x):
def while_x(self):
self.x += 10
if self.x <= 200:
self.parent.progress.setValue(self.x)
else:
self.timer.stop()
self.parent.btn_dir.setEnabled(True)
print(f'x = {self.x}')
Для моего перегруженного комплекса подошел путь упрощения процесса:
# m1.py
***
def ot(self): # клик по кнопке
thread1 = threading.Thread(target=self.progress_process, daemon=True)
thread1.start()
thread2 = threading.Thread(target=self.to_v)
thread2.start()
def ot_v(self): # просто запуск выполняемого скрипта
import otv.py
def progress_process(self): # любой счетчик
self.y = 0
self.progress.setValue(self.y)
for self.y in range(1, 101):
if self.y % 10 == 0:
self.progress.setValue(self.y)
if 99 > self.y > 90:
self.progress.setValue(self.y)
self.y = self.y + 1
***
