2012-08-08 60 views
1

我想用樣式表自定義QProgressBar的外觀。我想給它那動畫,'不確定'的樣子。所以我製作了一個動畫GIF,以保留QProgressBar::chunk的背景。QStyleSheet中的靜態Gif動畫

它顯示正常,但圖像是靜態的,沒有動畫。任何建議或解決方法?

我在OS X 10.8上運行PyQt 4.9.4。

回答

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 
     ... 
+0

多好的回答,@Eric!感謝您深入細節。我會將此標記爲正確的答案,因爲我認爲這將對大多數人有幫助。在我的確切情況下,我已經有一個異步過程來更新我的酒吧的進度。我想將動畫GIF作爲進度條的完成部分的背景,以便爲連續工作提供視覺印象。然而,也許一個小巧的,循環的QMovie在酒吧一側將會同樣有效。謝謝! – splodingsocks 2012-08-11 20:57:18

+0

哦,我明白了......我誤解了這個問題......那樣的話,我真的不知道答案,除非你定製了你有循環QMovie的地方,以及你影響基礎寬度的標籤在你完成的百分比。將是一個有用的部件壽。 – 2012-08-12 21:49:24