Изменение значения progress bar
Имеется такой код:
#main.py
import sys
from PyQt5 import QtWidgets
from main_window import MainWindow
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
#main_window.py
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtWidgets import *
from PyQt5.Qt import *
from PyQt5.QtCore import (Qt, QObject, QThread, pyqtSignal)
from ui_main_window import Ui_MainForm
from work_thread_class import WorkThread
class MainWindow(QtWidgets.QWidget, Ui_MainForm):
def __init__(self):
super().__init__()
self.setupUi(self)
self.progressBar.setDisabled(True)
self.generate()
def on_threadSignal(self, value):
self.progressBar.setValue(value)
def generate(self):
self.progressBar.setValue(1)
self.thread = WorkThread(self)
self.thread.threadSignal.connect(self.on_threadSignal)
self.thread.start()
if self.progressBar.value() > 80:
self.close_thread()
print("Поток закрыт")
#ui_main_window.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainForm(object):
def setupUi(self, MainForm):
MainForm.setObjectName("MainForm")
MainForm.resize(391, 508)
self.progressBar = QtWidgets.QProgressBar(MainForm)
self.progressBar.setEnabled(True)
self.progressBar.setGeometry(QtCore.QRect(20, 390, 351, 23))
self.progressBar.setMouseTracking(False)
self.progressBar.setProperty("value", 0)
self.progressBar.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop)
self.progressBar.setTextVisible(True)
self.progressBar.setOrientation(QtCore.Qt.Horizontal)
self.progressBar.setInvertedAppearance(False)
self.progressBar.setTextDirection(QtWidgets.QProgressBar.TopToBottom)
self.progressBar.setObjectName("progressBar")
self.retranslateUi(MainForm)
QtCore.QMetaObject.connectSlotsByName(MainForm)
def retranslateUi(self, MainForm):
_translate = QtCore.QCoreApplication.translate
MainForm.setWindowTitle(_translate("MainForm", "Loader"))
self.progressBar.setFormat(_translate("MainForm", "%p%"))
#work_thread_class.py
from PyQt5.QtCore import (Qt, QThread, pyqtSignal)
from loader_class import Loader
class WorkThread(QThread):
threadSignal = pyqtSignal(str)
def __init__(self, parent):
super().__init__()
self.parent = parent
def run(self):
progressBar_Value = 0
step = 1
k = 0
for i in range (0, 10):
for j in range (0, 10):
if k >= step:
k = 0
progressBar_Value += 1
self.parent.progressBar.setValue(progressBar_Value)
else:
k += 1
print("выполненo")
Программа должна во время прохода цикла изменять значение прогресс бара. Когда значение прогресс бара становится равным 80 поток должен закрыться.
В приведенном примере, программа зависает и закрывается.
Так же появилась надпись:
QWidget::repaint: Recursive repaint detected QObject::setParent: Cannot set parent, new parent is in a different thread
и почти почти после каждой итерации
QBackingStore::endPaint() called with active painter; did you forget to destroy it or call QPainter::end() on it?
Как решить эту проблему?
UDP: так же пробовал через эмитор передать значение
self.threadSignal.emit(progressBar_Value) ,
но сразу полностью зависает программа.
Ответы (1 шт):
Нельзя взаимодействовать с виджетами в дополнительном потоке.
Я отметил для вас как правильно взаимодействуют сигналы и слоты, попробуйте.
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.Qt import *
# ?from loader_class import Loader
#from ui_main_window import Ui_MainForm
class Ui_MainForm(object):
def setupUi(self, MainForm):
MainForm.setObjectName("MainForm")
MainForm.resize(391, 508)
self.progressBar = QtWidgets.QProgressBar(MainForm)
self.progressBar.setEnabled(True)
self.progressBar.setGeometry(QtCore.QRect(20, 390, 351, 23))
self.progressBar.setMouseTracking(False)
self.progressBar.setProperty("value", 0)
self.progressBar.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop)
self.progressBar.setTextVisible(True)
self.progressBar.setOrientation(QtCore.Qt.Horizontal)
self.progressBar.setInvertedAppearance(False)
self.progressBar.setTextDirection(QtWidgets.QProgressBar.TopToBottom)
self.progressBar.setObjectName("progressBar")
self.retranslateUi(MainForm)
QtCore.QMetaObject.connectSlotsByName(MainForm)
def retranslateUi(self, MainForm):
_translate = QtCore.QCoreApplication.translate
MainForm.setWindowTitle(_translate("MainForm", "Loader"))
self.progressBar.setFormat(_translate("MainForm", "%p%"))
#from work_thread_class import WorkThread
class WorkThread(QThread):
# threadSignal = pyqtSignal(str)
threadSignal = pyqtSignal(int) # +++
def __init__(self, parent):
super().__init__()
self.parent = parent
def run(self):
progressBar_Value = 0
for i in range(0, 10):
for j in range(0, 10):
progressBar_Value += 1
# self.parent.progressBar.setValue(progressBar_Value)
self.threadSignal.emit(progressBar_Value) # +++
self.msleep(100)
class MainWindow(QtWidgets.QWidget, Ui_MainForm):
def __init__(self):
super().__init__()
self.setupUi(self)
self.progressBar.setDisabled(True)
self.generate()
def on_threadSignal(self, value):
self.progressBar.setValue(value)
print(f'value = {value}')
if self.progressBar.value() > 79:
self.thread.terminate()
self.thread.wait()
print("Поток закрыт")
def generate(self):
self.progressBar.setValue(1)
self.thread = WorkThread(self)
self.thread.threadSignal.connect(self.on_threadSignal) # +++
self.thread.start()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
