如何从带参数的独立函数更新PyQt progressbar?

2024-04-26 18:59:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我想使用多个导入的函数和需要一些时间才能运行的参数。我想要一个“工作”进度条,跟踪该功能的进程。我已经回答了两个问题

  1. Connect an imported function to Qt5 progress bar without dependencies
  2. Report progress to QProgressBar using variable from an imported module

区别在于线程可以接受任何可以有参数的函数。函数也不需要yield返回进度条的百分比。进度条始终从0%开始

我从第一个链接复制了一个片段,并出于示例目的对其进行了修改

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) 

Tags: to函数进度条fromselfan参数init
1条回答
网友
1楼 · 发布于 2024-04-26 18:59:26

答案不要太复杂,因为它们仅限于一个非常特殊的上下文。通常,逻辑是向其传递一个QObject,该QObject更新百分比值,然后用该值发出信号。例如,一个简单的解决方案是使用线程模块:

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_())

相关问题 更多 >