如何使用 PySide、PyQt 创建一个加载进度条,就像我们在 Photoshop 中看到的那样

How to create a loading progress bar like we see in Photoshop with PySide,PyQt

这是我的代码。我正在尝试显示一个显示加载状态的进度条,直到所有小部件都正确加载但进度条不会更新 properly.It 仅在过程结束时更新并显示 100%

from PySide.QtGui import *
from PySide.QtCore import *
import time
import sys
class Mainwindow(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.progress = QProgressBar()
        self.progress.setRange(0, 100)
        self.worker = Worker()
        self.thread = QThread()
        self.worker.moveToThread(self.thread)
        self.worker.relay.connect(self.update_progress)
        self.thread.start()
        self.progress.show()
        self.add_tabs()

    def add_tabs(self):
        for i in xrange(10000):
            i*i
        time.sleep(1)
        self.worker.process()

        for i in xrange(10000):
            i*i
        time.sleep(1)
        self.worker.process()

        for i in xrange(10000):
            i*i
        time.sleep(1)
        self.worker.process()

        for i in xrange(10000):
            i*i
        time.sleep(1)
        self.worker.process()

        for i in xrange(10000):
            i*i
        time.sleep(1)
        self.worker.process()

        for i in xrange(10000):
            i*i
        time.sleep(1)
        self.worker.process()

        for i in xrange(10000):
            i*i
        time.sleep(1)
        self.worker.process()

        for i in xrange(10000):
            i*i
        time.sleep(1)
        self.worker.process()

        for i in xrange(10000):
            i*i
        time.sleep(1)
        self.worker.process()

        for i in xrange(10000):
            i*i
        time.sleep(1)
        self.worker.process()

    @Slot(int)
    def update_progress(self, x):
        self.progress.setValue(x * 10)

class Worker(QObject):
    relay = Signal(int)

    def __init__(self, parent=None):
        super(Worker, self).__init__(parent)
        self.x = 0

    def process(self):
        while self.x < 10:
            self.x = self.x+1
            self.relay.emit(self.x)
            print self.x
            return True

if __name__=='__main__':
    app=QApplication(sys.argv)
    win=Mainwindow()
    win.show()
    app.exec_()
    sys.exit(0)

编辑 1 据称我的问题是 how to make QtextEdit can update data realtime and no stuck UI 的重复,但我已经尝试过流程事件,流程事件是循环或我们在前端执行的流程。在我的例子中,你在 xrange 中看到的那些循环是我真实程序中的后端进程。此处使用 xrange 循环是为了理解,我有真正的后端任务 运行,我无法为其使用流程事件。抱歉,我一开始没有说清楚。我需要一个基于 Qthread 的解决方案。

如果我没理解错的话,您想在单独的线程上进行一些繁重的处理并在主 GUI 上更新进度。所以在 MainWindow.add_tabs 中完成的所有处理实际上应该在 worker 中完成。

此外,您似乎想使用 QProgressDialog(pop-up window) 而不是 QProgressBar

这是一个带有响应式 GUI 的解决方案:

from PySide.QtGui import *
from PySide.QtCore import *
import time
import sys

class Mainwindow(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.worker = Worker()
        self.thread = QThread()
        self.worker.moveToThread(self.thread)
        self.worker.workRequested.connect(self.thread.start)
        self.thread.started.connect(self.worker.add_tabs)
        self.worker.finished.connect(self.on_finish)

        self.button=QPushButton("Add tabs")
        self.button.clicked.connect(self.on_button_click)

        self.button_responsive=QPushButton("Still responsive?")
        self.button_responsive.clicked.connect(self.responsive)

        self.progress = QProgressDialog("Progress","cancel",0,10)
        self.progress.setCancelButton(None)
        self.worker.relay.connect(self.update_progress)

        vbox=QVBoxLayout()
        vbox.addWidget(self.button)
        vbox.addWidget(self.button_responsive)
        self.setLayout(vbox)

    def on_button_click(self):
        self.button.setEnabled(False)
        self.worker.request_work()
        self.progress.setValue(0)

    def on_finish(self):
        self.button.setEnabled(True)
        self.thread.quit()

    def update_progress(self,value):
        self.progress.setValue(value)

    def responsive(self):
        print("Yes!")


class Worker(QObject):
    workRequested=Signal()
    finished=Signal()
    relay=Signal(int)

    def __init__(self, parent=None):
        super(Worker, self).__init__(parent)
        self.x = 0

    def request_work(self):
        self.workRequested.emit()

    def add_tabs(self):
        self.x=0
        for i in range(10):
            #Do any processing
            for i in xrange(10000):
                i*i
            time.sleep(1)
            self.x+=1
            self.relay.emit(self.x)
        self.finished.emit()

if __name__=='__main__':
    app=QApplication(sys.argv)
    win=Mainwindow()
    win.show()
    sys.exit(app.exec_())