2012-11-19 116 views
3

我使用自定義QFileDialog,因爲我想選擇多個目錄。 但exec_函數是非常緩慢的,我不明白爲什麼。我正在使用最新版本的PyQt。PyQt QFileDialog exec_很慢

代碼段:

from PyQt4 import QtGui, QtCore, QtNetwork, uic 

class MainWindow(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     super(MainWindow, self).__init__(parent) 
     uic.loadUi('gui.ui', self)    
     self.connect(self.multiPackerAddDirsBtn, 
        QtCore.SIGNAL('clicked()'), self.multiPackerAddDirs) 

    def multiPackerAddDirs(self): 
     dialog = QtGui.QFileDialog(self) 
     dialog.setFileMode(QtGui.QFileDialog.Directory) 
     dialog.setOption(QtGui.QFileDialog.ShowDirsOnly, True) 
     dialogTreeView = dialog.findChild(QtGui.QTreeView) 
     dialogTreeView.setSelectionMode(
      QtGui.QAbstractItemView.ExtendedSelection) 
     if dialog.exec_(): 
      for dirname in dialog.selectedFiles(): 
       self.multiPackerDirList.addItem(str(dirname)) 
       print(str(dirname)) 

if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    window = MainWindow() 
    window.show() 
    app.exec_() 
+0

你在哪個平臺上?文件對話框*總是*緩慢,或者僅當您使用您發佈的代碼時? – ekhumoro

+0

我在Windows 7上。如果我使用像getSaveFileName這樣的預定義方法,它的速度很快,但是如果我使用dialog = QtGui.QFileDialog(self)創建一個自定義對話框,並使用dialog.exec_(),它就像地獄一樣慢。 – Ahsous

回答

3

QFileDialog構造函數創建一個Qt對話框,而靜態函數(如getSaveFileName)將創建一個原生一個(除非DontUseNativeDialog選項設置爲True)。

本機對話框可能比Qt更快或更慢,具體取決於使用的平臺。

對於某些平面,看起來問題可能更嚴重。請參閱this longstanding bug,它會影響使用Qt 4.7/4.8的Windows XP和Windows 7(以及其他版本)。

UPDATE

只是要清楚:

在Windows中,靜態函數QFileDialog.getExistingDirectory打開本地的「瀏覽文件夾」對話框中,只允許選擇一個目錄。所以Qt無法提供本地對話框來選擇多個目錄,因爲Windows不提供一個。

另一個主要的選擇是使用Qt自己的非本地文件對話框和猴子補丁,如this faq中所建議的。但是,正如您已經發現的那樣,目前由於底層實現中的錯誤而導致令人煩惱的緩慢的顯着缺點。

剩下的唯一選擇是編寫自己的目錄列表對話框,或者試着想辦法解決您的直接問題(即不使用文件對話框)。

+0

我試圖讓DontUseNativeDialog爲False,但沒有產生任何效果。 有沒有另一種方法來創建一個文件對話框,我可以選擇多個目錄? – Ahsous

+0

@Ahsous。沒有什麼可說的,但我儘可能地更新了答案。 – ekhumoro

0

我的默認Qt文件瀏覽器對話框的性能非常慢。列出一個目錄花費了大約5秒,選擇一個文件花了大約3秒。添加「DontUseNativeDialog」選項完全解決了我的問題。

file_path = QtGui.QFileDialog.getSaveFileName(self, 'Title', path, "", "", QtGui.QFileDialog.DontUseNativeDialog) 
print file_path