QProgressDialog的尸体徘徊 - 有时候

时间:2012-11-27 11:30:47

标签: python qt pyqt pyside

    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%,停止按钮为蓝色但不是脉冲。它没有反应。如果我移动应用程序窗口,它就会消失。

如果我在progress.setValue(numberOfLinesInFile)之后调用progress.destroy()似乎有帮助。但是从文档中复制示例并被叮咬似乎令人担忧,我不知道destroy()的后果。

我正在使用PySide,我切换到PyQt,同样的事情。

此外,有时progress.setValue(numberOfLinesInFile)会导致progress.wasCancelled()的后续读取返回false(但有时会返回true!)这就是我设置自己的progressWasCancelled的原因。它的随机性很令人不安。

我使用的是Mac 10.6.8,Qt 4.8.2,Python 2.7。尝试使用PySide 1.1.0和PyQt 4.9.4。

我这样做是错的吗?

1 个答案:

答案 0 :(得分:4)

我无法在Mac上测试,但我会尝试提出一些有助于解决问题的建议。

首先,如果您使用模态进度对话框,则无需调用processEvents(),因为对话框将自行处理。

其次,代码中的这一行:

    progress.setValue(lineNumber + 1)

是有问题的,因为要引用Qt docs

  

要使进度对话框按预期工作,您应该最初将此属性设置为0 最后将其设置为QProgressDialog :: maximum();你可以在中间任意多次调用setValue()。

所以你应该在循环之前调用progress.setValue(0),或者完全避免添加偏移量。此外,在最后一次迭代中,lineNumber + 1将等于最大值,此时对话框将reset(除非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_())