【问题标题】:wxpython: destroy cancelled ProgressDialogwxpython:销毁已取消的 ProgressDialog
【发布时间】:2016-09-20 00:51:57
【问题描述】:

我无法关闭 wx.ProgressDialog。如果过期;一切安好。单击取消或跳过将跳出对话框,但窗口在屏幕上永远保持冻结状态(控制流返回)。

import wx
def Progress(parent=None, message="", title="", maximum=3000):
  dlg = wx.GenericProgressDialog(title, message, maximum,style=wx.PD_AUTO_HIDE|wx.PD_APP_MODAL|wx.PD_CAN_SKIP|wx.PD_CAN_ABORT)
  keepGoing = True
  skip = False
  count = 0

  while keepGoing and (not skip) and count < maximum:
      count += 1
      wx.MilliSleep(1)
      wx.Yield()
      (keepGoing, skip_bogus) = dlg.Update(count)
      skip = dlg.WasSkipped()  #NOTE:  skip_bogus doesn't ever seem to update; even when skip button is clicked

  dlg.Destroy()
  wx.Yield()

  if not keepGoing:
      return "cancel"
  elif skip:
      return "skip" 
  else:
      return None

app = wx.App()
app.MainLoop()

Progress(None, "message", "title")

wxpython v3.0.2 python v2.7.10

【问题讨论】:

    标签: wxpython


    【解决方案1】:

    它可能在某种程度上取决于平台,但在 MainLoop 返回之后调用您的 Progress 函数对我来说是一个危险信号。顶级窗口在调用 Destroy 方法时不会被销毁,而是被添加到待处理的删除队列中,该队列稍后在事件循环中处理。

    尝试将对Process 的调用放在MainLoop 调用之前,并在Destroy 之后删除对wx.Yield 的调用。这适用于我在 OSX 和 Phoenix 上。

    【讨论】:

      【解决方案2】:

      这是LongRunningTask 的经典示例:您的while 循环将耗尽所有未用于事件处理的时间。当事件开始堆积时,GUI 变得无响应,并且 wxPython 不再能够及时处理任何事件(或处理对 wx.Yield() 的调用,就此而言)。

      该问题的解决方案是将阻塞事件/长时间运行的任务放在单独的线程中,并通过使用 e. G。 wx.CallAfter 工作完成后。

      研究上面给出的链接中的最后一个示例,Easiest Example *ever* :) 以了解如何做到这一点。

      【讨论】:

      • 这并不能解决问题。循环退出后,对话框不会被破坏。循环期间的 CPU 使用率无关紧要。
      • 诚然,您的示例适用于我,与您的 完全相同 配置(Python 事物 32 位,Win7 64 位)没有丝毫改变。即使@RobinDunn 提出的更改也没有必要。
      【解决方案3】:

      Robin 和 nepix32 的回答是很有价值的建议。另外,为什么不使用wx.Timer 来不断更新对话框呢?比如:

      class Progress:
          def __init__(self):
              self.dlg = wx.GenericProgressDialog(whatever)
              self.count = 0
      
          def Start(self):
              self._update()
              self.timer = wx.Timer(self.dlg)
              self.dlg.Bind(wx.EVT_TIMER, self._update, self.timer)
              self.timer.Start(1) # 1ms interval
      
          def _update(self, evt=None):
              self.count += 1
              if self.count == self.dlg.GetRange():
                  self._stop()
              else:
                  self.dlg.Update(self.count)
                  if self.dlg.WasSkipped() or self.dlg.WasCancelled():
                      self._stop()
      
          def _stop(self):
              self.timer.Stop()
              self.dlg.Close()
              wx.GetApp().ExitMainLoop()
      

      您的问题(如何关闭对话框)的答案是wx.GetApp().ExitMainLoop()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-16
        • 1970-01-01
        • 2020-06-23
        相关资源
        最近更新 更多