Реализация QProgressBar в потоке
Задача: из первого приложения (модуль m1.py) по кнопке вызывается второе приложение (модуль otv.py), в процессе выполнения которого, в statusBarпервого приложения (m1.py), отображается шкала ProgressBar.
Функционал в принципе работает, но криво и через одно место (третье приложение модуль b1.py). Кажется мне, в дальнейшем это аукнется, хотелось бы разобраться.
Трудности:
signaller.progress_chek.connect(self.signal)(вotv.py) – не работает, на мой взгляд, если в основном скрипте присутствуетtime.sleep- т.к. п.1 не работает, обновляем
ProgressBarчерезExample.signal(self, value=il) - для работы п.2 тянем из (
m1.py) в (otv.py)selfчерез (b1.py) - т.к.
Example.signalподвисает после 40% городим задержку и отслеживание окончания потока черезresult_a = threading.Event() / result_a.wait() / result_a.set(), хотя кажется это можно реализовать черезfinished = pyqtSignal()
P.S. в def while_x() проходит работа с .xlsx файлом, для краткости и наглядности приведен цикл.
m1.py
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
class Example(QtWidgets.QMainWindow):
def __init__(self):
super(Example, self).__init__()
QtWidgets.QMainWindow.__init__(self)
self.initUI(self)
def initUI(self, QProgressBar):
btn_dir = QtWidgets.QPushButton('Запуск')
btn_dir.clicked.connect(self.ot)
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.timeLine = QtCore.QTimeLine(1000 * 10) # проверка
# self.timeLine.setFrameRange(0, 100)
# self.timeLine.frameChanged.connect(self.signal)
# self.timeLine.start()
self.progressbar_self()
self.statusBar().insertPermanentWidget(1, self.progress)
self.statusBar().addPermanentWidget(btn_dir)
self.show()
def ot(self):
import otv
def progressbar_self(self):
import b1
b1.self = self
def progressbar_reset(self):
self.progress.reset()
def signal(self, value):
print(f'прогресс процесса {value} %')
self.progress.setValue(value)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec())
otv.py
from PyQt5.QtCore import (QDate, QObject, QEvent, pyqtSlot, pyqtSignal, QThread,
QTimeLine, QTimer, QSize, QSettings, QBasicTimer)
import os, sys
import time
import threading
from m1 import Example
from b1 import self
class Signaller(QObject):
progress_chek = pyqtSignal(int)
finished = pyqtSignal()
def func(signaller):
il = 0
signaller.progress_chek.emit(il)
# signaller.progress_chek.connect(self.signal)
Example.signal(self, value=il)
for il in range(1, 101):
if il % 10 == 0:
# signaller.progress_chek.emit(il)
# signaller.progress_chek.connect(self.signal)
Example.signal(self, value=il)
if il > 70:
time.sleep(1.0)
# signaller.progress_chek.emit(il)
# signaller.progress_chek.connect(self.signal)
Example.signal(self, value=il)
il = il + 1
if result_a.wait(timeout=0.1):
print()
print('\r ... на {}% закрыли поток ...'.format(il))
time.sleep(0.1)
# signaller.progress_chek.emit(100)
# signaller.progress_chek.connect(self.signal)
Example.signal(self, value=100)
break
signaller = Signaller()
result_a = threading.Event()
try:
# signaller.progress_chek.connect(self.signal)
# signaller.finished.connect(self.progressbar_reset)
thread = threading.Thread(target=func, args=(signaller,), daemon=True)
thread.start()
except Exception as exc:
print('ProgressBarа ! = ', exc)
print()
print('_______________________________________________________')
print()
def widg_gotov():
time.sleep(5.0)
print('обнулить ProgressBarа')
Example.progressbar_reset(self)
def while_x(x):
print('x1 =', x)
while x < 200:
x = x+10
time.sleep(0.4)
print('x2 =', x)
x = 0
while_x(x)
print()
print('1: thread.isAlive =', thread.isAlive())
if thread.isAlive():
result_a.set()
time.sleep(1.0)
print('2: thread.isAlive =', thread.isAlive())
widg_gotov()
print('_______________________________________________________')
b1.py
self = []
if __name__ == '__main__':
print()
Ответы (1 шт):
Автор решения: S. Nick
→ Ссылка
Sorry, я ничего не понял в вашей солянке. Если я вас правильно понял, это может выглядеть примерно так. Если это то что вы хотите и вам что-то не понятно - спросите.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
from PyQt5.Qt import *
class Thread(QtCore.QThread):
progress_chek = pyqtSignal(int)
finished = pyqtSignal()
def __init__(self):
super().__init__()
self.x = 0
def run(self):
while self.x <= 200:
self.progress_chek.emit(self.x)
self.x += 10
self.msleep(400)
#print('x2 =', self.x)
self.finished.emit()
class Example(QtWidgets.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.centralWidget = QtWidgets.QWidget()
self.setCentralWidget(self.centralWidget)
self.frame = QtWidgets.QFrame()
self.frame.setStyleSheet("background-color: rgb(146, 43, 63);")
self.label = QLabel()
self.label.setStyleSheet("color: #FBFFE2; font-size: 22px;")
layoutH = QtWidgets.QHBoxLayout(self.frame)
layoutH.addWidget(self.label, alignment = Qt.AlignCenter)
self.btn_dir = QtWidgets.QPushButton('Запуск')
self.btn_dir.clicked.connect(self.ot)
self.progress = QtWidgets.QProgressBar(self, minimum=0, maximum=200)
self.progress.setObjectName("progress")
self.progress.setStyleSheet('text-align: center; '
'min-height: 20px; max-height: 20px;')
layout = QtWidgets.QGridLayout(self.centralWidget)
layout.addWidget(self.frame, 0, 0, 1, 2)
layout.addWidget(self.progress, 1, 0)
layout.addWidget(self.btn_dir, 1, 1)
self.thread = Thread()
self.thread.progress_chek.connect(self.update_progressbar)
self.thread.finished.connect(self.finished_progressbar)
def update_progressbar(self, val):
self.progress.setValue(val)
if val*0.1 % 2:
self.label.setText("Выполняется процесс, ожидайте ...")
else:
self.label.setText("Выполняется процесс, ожидайте ")
def finished_progressbar(self):
self.btn_dir.setEnabled(True)
self.label.clear()
msg = QtWidgets.QMessageBox.information(
self,
'ВНИМАНИЕ',
'Процесс завершен - можете закрывать окно!'
)
self.progress.reset()
def ot(self):
self.thread.x = 0
self.progress.reset()
self.progress.setValue(0)
self.thread.start()
self.btn_dir.setEnabled(False)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = Example()
ex.resize(500, 300)
ex.show()
sys.exit(app.exec())


