如何使用 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_())
这是我的代码。我正在尝试显示一个显示加载状态的进度条,直到所有小部件都正确加载但进度条不会更新 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_())