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。
我这样做是错的吗?
答案 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_())