如何确保PyQt中显示QProgressDialog

时间:2013-11-04 00:34:38

标签: python user-interface pyqt pyside qprogressbar

有时我的QProgressDialog显示,有时它根本不会显示(好像没有调用processEvents)。是否有任何processEvents()命令的工件可能导致QProgressDialog在某些情况下不显示?

我的问题很笼统,因为我还没有能够在我的代码中找出问题所在。但是,我注意到当我使用配置解析器访问文本文件时,我的QProgressDialog没有显示它。解决方法是在文件关闭后执行time.sleep()(可能是为了确保进程完成,然后processEvents将开始显示QProgressDialog)。

如果有帮助,这是我将QProgressDialog作为生成器运行的代码:

def progress_dialog(self, data, label, window_title, stop_label, capture_bar=False):
    bar = QProgressDialog(label, stop_label, 0, len(data))
    if capture_bar: self.prog_bar = bar
    bar.setWindowTitle(window_title)
    for k, d in enumerate(data):
        QCoreApplication.instance().processEvents()
        if bar.wasCanceled():
            raise GeneratorExit
        # set the next value beyond the start of 0
        bar.setValue(k+1)
        # again process events to draw the new label and value
        QCoreApplication.instance().processEvents()
        yield(d)
        raise StopIteration

再次,抱歉,我没有孤立问题的完整代码片段(并且完整代码太大了)。我想我正在寻找的是检查processEvents()命令是否正在执行其工作的原因(因为我正在调用它,但它挂起在其他进程而不是显示对话框)。

编辑:

根据此支持请求执行“bar.show()”命令将强制显示进度条。

http://redmine.smar.fi/issues/265

我要等几周,确保这是一个有保障的修复方法,然后再将其作为答案发布。

3 个答案:

答案 0 :(得分:3)

如果您需要显示QProgessDialog而不管进程的持续时间,请使用其setMinimumDuration方法,其值为0.根据文档,默认最小值为4000毫秒。

答案 1 :(得分:1)

根据此支持请求,执行bar.show()命令将强制进度条显示: http://redmine.smar.fi/issues/265

在每次show()调用之前和首次构建进度条之后,只需调用process events方法。

我已经等了将近4个月了,这个解决方案还没有失败。似乎是一个充分的答案。

答案 2 :(得分:1)

这可能是一个旧线程,但我有一个类似的问题,show()使对话框出现,但是空。所以,我想出了这个装饰器,我应用于我想要运行阻塞的函数,同时允许GUI线程处理事件。

def nongui(fun):
    """Decorator running the function in non-gui thread while
    processing the gui events."""
    from multiprocessing.pool import ThreadPool
    from PyQt4.QtGui import QApplication

    def wrap(*args, **kwargs):
        pool = ThreadPool(processes=1)
        async = pool.apply_async(fun, args, kwargs)
        while not async.ready():
            async.wait(0.01)
            QApplication.processEvents()
        return async.get()

    return wrap

然后,通过装饰器正常编写计算函数很容易:

@nongui
def work(input):
    # Here you calculate the output and set the 
    # progress dialog value
    return out

然后像往常一样运行它:

out = work(input)