python - 定期更新带有标签的 ProgressBar

标签 python python-3.x pyqt pyqt5

我正在开发一个应用程序,我需要使用 QProgressBar 来让用户了解进度。但是,我不想按步骤更新进度条,而是想使用 setMaximum(0) 在进度条上显示“忙碌”指示器并更新 QLabel 以显示当前阶段。我这样做是为了让一切变得简单。

这是一个模拟 UI,用于简化说明。

enter image description here

这是相应的代码:

class TestWindow(QMainWindow):
  def __init__(self):
    super().__init__()
    relpath = 'ui/test.ui'
    uifile = join(dirname(sys.argv[0]), relpath)
    uic.loadUi(uifile, self)
    self.pushButton.clicked.connect(self.start_updating)

  def start_updating(self):
    self.progressBar.setMaximum(0)
    self.label.setText("Func 1")
    sleep(3) # in real app do something here
    self.label.setText("Func 2")
    sleep(3) # in real app do something else here
    self.label.setText("Func 3")


if __name__ == "__main__":
  app = QApplication(sys.argv)
  window = TestWindow()
  window.show()
  sys.exit(app.exec_())

如果我运行此命令,则仅显示 QLabel 的最后一个状态(“Func 3”),并且直到最后一次更新标签文本之前,进度条上不会显示“忙碌”模式。谁能帮助我理解为什么这不起作用以及是否有更好的方法来定期更新标签?

最佳答案

您不应该在 GUI 线程中执行繁重的任务,因为它们会阻止事件循环,从而阻止 GUI 更新,例如在您的情况下,标签未更新。相反,您必须在另一个线程中执行该任务并通过信号发送更新 GUI 的信息:

import os
import sys
import time

from PyQt5 import QtCore, QtGui, QtWidgets, uic


class Worker(QtCore.QObject):
    textChanged = QtCore.pyqtSignal(str)
    started = QtCore.pyqtSignal()
    finished = QtCore.pyqtSignal()

    @QtCore.pyqtSlot()
    def run_task(self):
        self.started.emit()
        self.textChanged.emit("Func 1")
        time.sleep(3)  # in real app do something here
        self.textChanged.emit("Func 2")
        time.sleep(3)  # in real app do something else here
        self.textChanged.emit("Func 3")
        self.finished.emit()


class TestWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        relpath = "ui/test.ui"
        current_dir = os.path.dirname(os.path.realpath(__file__))
        uifile = os.path.join(current_dir, relpath)
        uic.loadUi(uifile, self)

        thread = QtCore.QThread(self)
        thread.start()

        self.m_worker = Worker()
        self.m_worker.moveToThread(thread)
        self.m_worker.started.connect(self.onStarted)
        self.m_worker.finished.connect(self.onFinished)
        self.m_worker.textChanged.connect(self.update_label)

        self.pushButton.clicked.connect(self.m_worker.run_task)
        self.progressBar.setValue(0)

    @QtCore.pyqtSlot()
    def onStarted(self):
        self.progressBar.setMaximum(0)
        self.pushButton.setEnabled(False)

    @QtCore.pyqtSlot()
    def onFinished(self):
        self.progressBar.setMaximum(1)
        self.progressBar.setValue(1)
        self.pushButton.setEnabled(True)

    @QtCore.pyqtSlot(str)
    def update_label(self, text):
        self.label.setText(text)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = TestWindow()
    window.show()
    sys.exit(app.exec_())

关于python - 定期更新带有标签的 ProgressBar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57162569/

相关文章:

python - 无法在 QFileDialog 中为文件添加扩展名

python - 如何将一个函数中的多个变量用于另一个函数?

python - 你能解释一下代码的第 8 行和第 9 行是如何工作的吗?

python - 在 Python 中解析多行

qt - PyQt5 QSystemTrayIcon 在实际托盘之外

python - PyQt5程序不显示小部件

python - 在Python中加载未知数量的pickle对象

python - 如何在 Python 3.2 中选择输入

python - 保存 Tkinter Canvas 对象

python - 如何在 Python 中检查 Selenium Webdriver 中的单击是否更改了页面