【问题标题】:How to update progress bar while performing a task如何在执行任务时更新进度条
【发布时间】:2012-11-30 21:58:42
【问题描述】:

我想使用 wx.ProgressDialog 来显示我的程序的进度。我有一个按钮,按下时会运行此功能:

def runmiP(self, event):
    predictor.runPrediction(self.uploadProtInterestField.GetValue(), self.uploadAllProteinsField.GetValue(), self.uploadPfamTextField.GetValue(), \
                   self.edit_eval_all.Value, self.edit_eval_small.Value, self.saveOutputField)

predictor 是我写的一个 python 包。如何从预测器中获取进度并将其显示在进度条中?我只能返回一个值。我应该多次调用它(比如每分钟),记住它离开的位置,返回它有多远并再次调用它?像

while 1: 
    time.sleep(60)
    predictor.runPrediction(self.uploadProtInterestField.GetValue(), self.uploadAllProteinsField.GetValue(), self.uploadPfamTextField.GetValue(), \
                   self.edit_eval_all.Value, self.edit_eval_small.Value, self.saveOutputField)

或者有更好的方法吗?

【问题讨论】:

    标签: python multithreading wxpython progress-bar


    【解决方案1】:

    这是一个普遍的问题。 (除非您已经在另一个线程上运行它,否则您会阻塞整个 UI,而不仅仅是无法更新进度条,对吗?)并且有两种通用方法可以解决它。

    • 将回调传递给 runPrediction,并使其在循环中每 X 次、每 Y% 或每 Z 秒调用一次 progressCallback(sofar, total)。 (您可以使用其他一些通信机制——发布到队列并触发条件、通过管道或套接字发送消息等——但想法是一样的。)

    • 将 runPrediction 分解为可以按顺序运行的单独的较小作业,并在每次启动下一个作业时更新进度。

    您的解决方案基本上是第二个想法的稍微笨拙但通常完全合理的版本。如果没有明确的方法来分解工作,但有一种合理的方法可以中止工作,将工作存放在原处,然后再继续,这实际上与分解工作是一回事,对吧?

    Python 提供了一种通常更简单、更简洁的方法来实现第二个想法:将 runPrediction 变成一个生成器,它会在结果进入时产生结果,而不是在最后返回所有结果。然后,您只需在每个值返回时更新进度。

    【讨论】:

    • 回调并不总是有效,因为它不会运行允许进度 UI 重新绘制自身的消息循环。
    • @MarkRansom:我在第一段中已经提到:“除非您已经在另一个线程上运行它,否则您会阻塞整个 UI,而不仅仅是无法更新进度条”。
    • 抱歉,您好像在说回调是解决该问题的方法。
    • @MarkRansom:对于像wx 这样的更新的90 年代风格的框架,您可以在另一个线程中进行后台工作,您可以直接从该线程更新GUI,因此将回调传递给做到这一点,更新就是你所需要的。 (如果 GUI 不是线程安全的,回调将不得不通过 runOnMainThread 方法或通过发布事件来完成它的 GUI 工作。)如果你使用单线程 SafeYield 解决方案,你可以只是补习SafeYield 进入回调。但无论如何,runmiP 本身看起来是一样的。当然你说得对,对于某些类型的 GUI,这根本不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-16
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 2019-11-08
    • 2010-11-11
    相关资源
    最近更新 更多