我想用样式表自定义QProgressBar的外观。我想给它一个动画的,“不确定的”外观。所以我制作了一个动画GIF,以便留在QProgressBar::chunk
的背景中。
它显示正常,但图像是静态的,没有动画。有任何建议或解决方法吗?
我在OS X 10.8上运行PyQt 4.9.4。
答案 0 :(得分:3)
所以,这是你面临的一个稍微复杂的问题。
QProgressBar依赖来自循环或某些确定数量的信息来表示完成百分比。当您通过代码设置值时,Qt将设置进度条的值,重新绘制它,从而显示更新的值。这实际上需要在循环中进行几毫秒的处理。如果你没有这样做,那么Qt的优化就不会重绘。这是同步的。
Web上使用了“不确定”的外观(如AJAX gif微调器或条形码),因为该进程实际上已从客户端移出并正在服务器上处理并正在等待响应。客户端的进程根本没有被阻止,因此可以随意更新电影的界面。
您可以在QLabel中使用QMovie来实现您的目标:
movie = QMovie()
movie.setFileName('/path/to/ajax_loader.gif')
movie.start()
label = QLabel(parent)
label.setMovie(movie)
这将使你的不确定的旋转器。但是,只有事件循环处理事件时才会播放。一旦你开始实际的工作进程,它就会阻止事件循环,所以你的电影将开始播放。
您需要将事件实际“泵”到循环中的播放器以使其更新。您可以通过以下方式执行此操作:
app = QApplication.instance()
# show my label
label.show()
for obj in objs:
# process stuff on my obj
app.processEvents()
# hide the label
label.hide()
当然,根据你在循环中所做的每个动作花费多长时间,你的微调器/加载器电影将“卡住”直到再次处理事件。
真的,实现你想要的外观的最好方法是使用线程应用程序。您可以使用QThread执行所有操作,并在处理时向用户显示加载程序图像。这更类似于ajax的工作方式 - 主要的Qt事件循环将继续运行,因为您的工作线程处理所有内容 - 在未知的时间内。这是异步的。
类似的东西:
class MyThread(QThread):
def run( self ):
# perform some actions
...
class MyDialog(QDialog):
def __init__( self, parent ):
# initialize the dialog
...
self._thread = MyThread(self)
self._thread.finished.connect(self.refreshResults)
self.refresh()
def refresh( self ):
# show the ajax spinner
self._ajaxLabel.show()
# start the thread and wait for the results
self._thread.start()
def refreshResults( self ):
# hide the ajax spinner
self._ajaxLabel.hide()
# process the thread results
...
我有一个加载器小部件,每当我在GUI库中执行此类操作时,我都会使用它。如果你想查看它的代码/使用它,它在http://dev.projexsoftware.com/projects/projexui,类是XLoaderWidget(projexui.widgets.xloaderwidget)
设置与上面相同,但只是:
from projexui.widgets.xloaderwidget import XLoaderWidget
class MyThread(QThread):
def run( self ):
# perform some actions
...
class MyDialog(QDialog):
def __init__( self, parent ):
# initialize the dialog
...
self._thread = MyThread(self)
self._thread.finished.connect(self.refreshResults)
self.refresh()
def refresh( self ):
# show the ajax spinner
XLoaderWidget.start(self)
# start the thread and wait for the results
self._thread.start()
def refreshResults( self ):
# hide the ajax spinner
XLoaderWidget.stop(self)
# process the thread results
...