xtlc
19th March 2020, 11:05
I am trying to update a QDialogs labels with a background process in two ways: Via a STATUS class and a Result function I post in the end. I think the QDialog prevents my functions in the back to be executed, as the console output is also only generated once I close the QDialog:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QDialog, QApplication, QMessageBox, QDialogButtonBox, QLabel, QInputDialog
from PyQt5.QtGui import QBrush, QColor
from PyQt5.QtCore import QTimer, QThreadPool, QRunnable, QObject, Qt, pyqtSlot, pyqtSignal
from datetime import datetime
import traceback, sys
class AppWindow(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.threadpool = QThreadPool()
self.ui.setupUi(self)
self.results = 0
self.STATI = [Status(ID=i, callback=self.postStatus) for i in range(2)]
self.show()
self.ui.Button.clicked.connect(self.Button_clkd)
def OkButton_clkd(self):
self.ui.resultBox.close()
def postStatus(self, STATUS):
lables_list_qdialog = self.ui.resultBox.findChildren(QtWidgets.QLabel)
lables_list_qdialog[STATUS.id].setText("Slot "+ str(STATUS.id) +" job: "+ STATUS.status)
self.ui.res_0_label.setText("postStatus working")
def postResult(self, job):
self.results += 1
lables_list_qdialog = self.ui.resultBox.findChildren(QtWidgets.QLabel)
lables_list_qdialog[job["id"]].setText(job["result"]+ "--" +job["arg"])
self.ui.res_1_label.setText("postResult working")
def workFunc(self, *argv):
self.ui.resultWindow(self)
self.total_jobs = 0
self.jobs = {0: {"id": 0, "time": datetime.now(), "result": None, "arg": "Hello", "func": argv[0].__name__},
1: {"id": 1, "time": datetime.now(), "result": None, "arg": "World", "func": argv[0].__name__}}
for job in self.jobs:
self.total_jobs += 1
self.STATI[job].reset()
worker = Worker(argv[0], self.jobs[job], argv[1], self.STATI[job])
worker.signals.result.connect(self.postResult)
self.threadpool.start(worker)
def Button_clkd(self):
self.workFunc(self.test, "testing parameter")
def test(self, job, arg, STATUS):
STATUS.update("Test executing")
secs = datetime.now() - job["time"]
job["time"] = secs.seconds
job["result"] = arg
return job
class Worker(QRunnable):
def __init__(self, func, *args):
super().__init__()
self.func = func
self.args = args
self.signals = WorkerSignals()
@pyqtSlot()
def run(self):
try:
result = self.func(*self.args)
print(result)
except:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit((exctype, value, traceback.format_exc()))
else:
self.signals.result.emit(result)
finally:
self.signals.finished.emit()
class WorkerSignals(QObject):
finished = pyqtSignal()
error = pyqtSignal(tuple)
result = pyqtSignal(object)
class Status():
def __init__(self, ID, callback=lambda callbackparameter: None):
self.status = ""
self.callback = callback
self.id = ID
def update(self, callbackparameter):
self.status = callbackparameter
self.callback(self)
def reset(self):
self.status = ""
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(200, 200)
Dialog.setWindowTitle("test")
self.res_0_label = QtWidgets.QLabel(Dialog)
self.res_0_label.setGeometry(QtCore.QRect(10, 100, 120, 40))
self.res_0_label.setText("id 0 job: ...")
self.res_1_label = QtWidgets.QLabel(Dialog)
self.res_1_label.setGeometry(QtCore.QRect(10, 120, 120, 40))
self.res_1_label.setText("id 1 job: ...")
self.Button = QtWidgets.QPushButton(Dialog)
self.Button.setGeometry(QtCore.QRect(40, 40, 140, 40))
self.Button.setObjectName("Button")
self.Button.setText("WORK!")
def resultWindow(self, parent):
self.resultBox = QDialog(parent)
self.resultBox.installEventFilter(parent)
self.resultBox.setWindowTitle("Please Wait")
self.resultBox.setGeometry(300, 300, 360, 200)
self.OkButton = QtWidgets.QPushButton(self.resultBox)
self.OkButton.setGeometry(QtCore.QRect(130, 160, 100, 40))
self.OkButton.setText("Ok")
self.OkButton.clicked.connect(parent.OkButton_clkd )
self.job_0_label = QtWidgets.QLabel(self.resultBox)
self.job_0_label.setGeometry(QtCore.QRect(10, 10, 300, 40))
self.job_0_label.setText("Slot 0 job: IDLE ...")
self.job_1_label = QtWidgets.QLabel(self.resultBox)
self.job_1_label.setGeometry(QtCore.QRect(10, 30, 300, 40))
self.job_1_label.setText("Slot 1 job: IDLE ...")
self.resultBox.exec_()
if __name__ == "__main__":
app = QApplication(sys.argv)
w = AppWindow()
w.show()
sys.exit(app.exec_())
This snippet basically describes my pain: Once executed it should update the labels in the QDialog ResultBox. But it does not. Please enlighten me :) Also, how can I find all labels in my Ui_Dialog class that are inside the setupUi method? .findChildren does work for resultbox (see code) but I fail to apply the principle on the Ui_Dialog.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QDialog, QApplication, QMessageBox, QDialogButtonBox, QLabel, QInputDialog
from PyQt5.QtGui import QBrush, QColor
from PyQt5.QtCore import QTimer, QThreadPool, QRunnable, QObject, Qt, pyqtSlot, pyqtSignal
from datetime import datetime
import traceback, sys
class AppWindow(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.threadpool = QThreadPool()
self.ui.setupUi(self)
self.results = 0
self.STATI = [Status(ID=i, callback=self.postStatus) for i in range(2)]
self.show()
self.ui.Button.clicked.connect(self.Button_clkd)
def OkButton_clkd(self):
self.ui.resultBox.close()
def postStatus(self, STATUS):
lables_list_qdialog = self.ui.resultBox.findChildren(QtWidgets.QLabel)
lables_list_qdialog[STATUS.id].setText("Slot "+ str(STATUS.id) +" job: "+ STATUS.status)
self.ui.res_0_label.setText("postStatus working")
def postResult(self, job):
self.results += 1
lables_list_qdialog = self.ui.resultBox.findChildren(QtWidgets.QLabel)
lables_list_qdialog[job["id"]].setText(job["result"]+ "--" +job["arg"])
self.ui.res_1_label.setText("postResult working")
def workFunc(self, *argv):
self.ui.resultWindow(self)
self.total_jobs = 0
self.jobs = {0: {"id": 0, "time": datetime.now(), "result": None, "arg": "Hello", "func": argv[0].__name__},
1: {"id": 1, "time": datetime.now(), "result": None, "arg": "World", "func": argv[0].__name__}}
for job in self.jobs:
self.total_jobs += 1
self.STATI[job].reset()
worker = Worker(argv[0], self.jobs[job], argv[1], self.STATI[job])
worker.signals.result.connect(self.postResult)
self.threadpool.start(worker)
def Button_clkd(self):
self.workFunc(self.test, "testing parameter")
def test(self, job, arg, STATUS):
STATUS.update("Test executing")
secs = datetime.now() - job["time"]
job["time"] = secs.seconds
job["result"] = arg
return job
class Worker(QRunnable):
def __init__(self, func, *args):
super().__init__()
self.func = func
self.args = args
self.signals = WorkerSignals()
@pyqtSlot()
def run(self):
try:
result = self.func(*self.args)
print(result)
except:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit((exctype, value, traceback.format_exc()))
else:
self.signals.result.emit(result)
finally:
self.signals.finished.emit()
class WorkerSignals(QObject):
finished = pyqtSignal()
error = pyqtSignal(tuple)
result = pyqtSignal(object)
class Status():
def __init__(self, ID, callback=lambda callbackparameter: None):
self.status = ""
self.callback = callback
self.id = ID
def update(self, callbackparameter):
self.status = callbackparameter
self.callback(self)
def reset(self):
self.status = ""
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(200, 200)
Dialog.setWindowTitle("test")
self.res_0_label = QtWidgets.QLabel(Dialog)
self.res_0_label.setGeometry(QtCore.QRect(10, 100, 120, 40))
self.res_0_label.setText("id 0 job: ...")
self.res_1_label = QtWidgets.QLabel(Dialog)
self.res_1_label.setGeometry(QtCore.QRect(10, 120, 120, 40))
self.res_1_label.setText("id 1 job: ...")
self.Button = QtWidgets.QPushButton(Dialog)
self.Button.setGeometry(QtCore.QRect(40, 40, 140, 40))
self.Button.setObjectName("Button")
self.Button.setText("WORK!")
def resultWindow(self, parent):
self.resultBox = QDialog(parent)
self.resultBox.installEventFilter(parent)
self.resultBox.setWindowTitle("Please Wait")
self.resultBox.setGeometry(300, 300, 360, 200)
self.OkButton = QtWidgets.QPushButton(self.resultBox)
self.OkButton.setGeometry(QtCore.QRect(130, 160, 100, 40))
self.OkButton.setText("Ok")
self.OkButton.clicked.connect(parent.OkButton_clkd )
self.job_0_label = QtWidgets.QLabel(self.resultBox)
self.job_0_label.setGeometry(QtCore.QRect(10, 10, 300, 40))
self.job_0_label.setText("Slot 0 job: IDLE ...")
self.job_1_label = QtWidgets.QLabel(self.resultBox)
self.job_1_label.setGeometry(QtCore.QRect(10, 30, 300, 40))
self.job_1_label.setText("Slot 1 job: IDLE ...")
self.resultBox.exec_()
if __name__ == "__main__":
app = QApplication(sys.argv)
w = AppWindow()
w.show()
sys.exit(app.exec_())
This snippet basically describes my pain: Once executed it should update the labels in the QDialog ResultBox. But it does not. Please enlighten me :) Also, how can I find all labels in my Ui_Dialog class that are inside the setupUi method? .findChildren does work for resultbox (see code) but I fail to apply the principle on the Ui_Dialog.