Issue
I want to use multiple imported function with arguments that takes some while to run. I want a 'working' progress bar that track the processes of that function. I have followed 2 questions already here.
- Connect an imported function to Qt5 progress bar without dependencies
- Report progress to QProgressBar using variable from an imported module
The difference is that the thread can take any function which can have arguments. The function also not needs to yield
the percent to return to the progressbar. The progressbar always start at 0%.
I copied a snippet from first link and modified it for example purpose.
from external_script import long_running_function
class Actions(QDialog):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('Progress Bar')
self.progress = QProgressBar(self)
self.button = QPushButton('Start', self)
self.show()
self.button.clicked.connect(self.onButtonClick)
def onButtonClick(self):
long_running_function(**kwargs) # This can be any function that takes argument/s
self.progress.setValue(value)
Solution
Do not get too complicated with the answers as they are limited to a very particular context. In general the logic is to pass a QObject to it that updates the percentage value and then emits a signal with that value. For example a simple solution is to use the threading module:
import sys
import threading
from PyQt5 import QtCore, QtWidgets
class PercentageWorker(QtCore.QObject):
started = QtCore.pyqtSignal()
finished = QtCore.pyqtSignal()
percentageChanged = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super().__init__(parent)
self._percentage = 0
@property
def percentage(self):
return self._percentage
@percentage.setter
def percentage(self, value):
if self._percentage == value:
return
self._percentage = value
self.percentageChanged.emit(self.percentage)
def start(self):
self.started.emit()
def finish(self):
self.finished.emit()
class FakeWorker:
def start(self):
pass
def finish(self):
pass
@property
def percentage(self):
return 0
@percentage.setter
def percentage(self, value):
pass
import time
def long_running_function(foo, baz="1", worker=None):
if worker is None:
worker = FakeWorker()
worker.start()
while worker.percentage < 100:
worker.percentage += 1
print(foo, baz)
time.sleep(1)
worker.finish()
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.progress = QtWidgets.QProgressBar()
self.button = QtWidgets.QPushButton("Start")
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.button)
lay.addWidget(self.progress)
self.button.clicked.connect(self.launch)
def launch(self):
worker = PercentageWorker()
worker.percentageChanged.connect(self.progress.setValue)
threading.Thread(
target=long_running_function,
args=("foo",),
kwargs=dict(baz="baz", worker=worker),
daemon=True,
).start()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
Answered By - eyllanesc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.