2012-11-27 84 views
3
progress = QtGui.QProgressDialog("Parsing Log", "Stop", 0,numberOfLinesInFile , self) 
    progress.setWindowModality(QtCore.Qt.WindowModal) 

    for lineNumber, line in enumerate(file): 
     # yield a bit to the Qt UI handler 
     QtGui.QApplication.processEvents() 
     progress.setValue(lineNumber + 1) # lineNumber is zero-based so need the plus one to match the more literal numberOfLinesInFile 
     if progress.wasCanceled(): 
      progressWasCancelled = True 
      break 


     # ...read and parse lines from file (20mb takes ~10 seconds) 


    # crank the progress bar through to completion to get rid of it 
    # this seems to forgo the opportunity to use progress.wasCanceled() subsequently? 
    progress.setValue(numberOfLinesInFile) 


    if not progressWasCancelled: 
     self.updateTable(self.requestRoster) 

此後,無論進度對話是否被取消,隱藏進度對話框(它滑回工具欄)。但是,如果我切換應用程序(Mac上的'命令選項卡'),然後切換回我的應用程序,QProgressDialog的一個幻影就在主應用程序窗口的前面!它的進度條是100%,停止按鈕是藍色的,但沒有脈衝。它沒有反應。如果我移動應用程序窗口,它會消失。QProgressDialog屍體徘徊 - 有時

如果我在progress.setValue(numberOfLinesInFile)之後調用progress.destroy(),這似乎有幫助。但似乎令人擔心的是從文檔中複製示例並被咬傷,而我不知道destroy()的後果。

我正在使用PySide,我切換到PyQt和相同的東西。

此外,有時progress.setValue(numberOfLinesInFile)導致後續讀取progress.wasCancelled()返回false(但有時它返回true!),這就是爲什麼我設置我自己的​​。它的隨機性令人不安。

我在Mac 10.6.8,Qt 4.8.2,Python 2.7。試用PySide 1.1.0和PyQt 4.9.4。

我這樣做全錯嗎?

+0

請不要問兩個不相關的問題於一身。您應該將有關進度欄的部分作爲單獨的問題發佈。 – sashoalm

+0

@satuon。這裏肯定沒有兩個不相關的問題,所以我已經把你的編輯推回去了。在不進行太多細節的情況下,進度對話框中的'setValue()'函數不僅僅是更新進度條小部件,它的功能更多。 – ekhumoro

回答

3

我無法在Mac上測試,但我會嘗試提出一些可以幫助解決問題的建議。

首先,如果使用模態進度對話框,則不需要調用processEvents(),因爲對話框本身將處理此對話框。

其次,這一行代碼:

progress.setValue(lineNumber + 1) 

是有問題的,因爲引用Qt docs

對於進度對話框按預期方式工作,你應該最初設置該屬性0最後將其設置爲QProgressDialog :: maximum();你可以在中間調用setValue()任意次數。

因此,您應該在循環之前調用progress.setValue(0),或者完全避免添加偏移量。另外,在最後一次迭代中,lineNumber + 1將等於最大值,這將在該點的對話框(除非autoReset已被設置爲False)。正是由於這個原因,Qt示例在循環完成後調用setValue(maximum)

最後,在完成進度對話框後調用destroy()deleteLater()沒有問題 - 實際上,這是個好主意。當您將self傳遞給QProgressDialog構造函數時,它將成爲對話框的父項,並且保留對其的引用。因此,除非您明確地刪除它,否則每次調用使用它的函數時(可能會浪費大量內存),都會添加一個新的子對話框(及其所有子對象)。

這裏有一個演示腳本,可能是改良:

import sys, time 
from PyQt4 import QtGui, QtCore 

class Window(QtGui.QWidget): 
    def __init__(self): 
     QtGui.QWidget.__init__(self) 
     self.button = QtGui.QPushButton('Test', self) 
     self.button.clicked.connect(self.handleButton) 
     layout = QtGui.QVBoxLayout(self) 
     layout.addWidget(self.button) 

    def handleButton(self): 
     file = range(30) 
     numberOfLinesInFile = len(file) 
     progressWasCancelled = False 
     progress = QtGui.QProgressDialog(
      "Parsing Log", "Stop", 0, numberOfLinesInFile, self) 
     progress.setWindowModality(QtCore.Qt.WindowModal) 
     progress.setMinimumDuration(0) 
     for lineNumber, line in enumerate(file): 
      progress.setValue(lineNumber) 
      if progress.wasCanceled(): 
       progressWasCancelled = True 
       break 
      time.sleep(0.05) 
     progress.setValue(numberOfLinesInFile) 
     print 'cancelled', progress.wasCanceled(), progressWasCancelled 
     progress.deleteLater() 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    window = Window() 
    window.show() 
    sys.exit(app.exec_()) 
+0

完美地工作,謝謝! – scottydelta