2016-09-20 3 views
0

Я не могу получить wx.ProgressDialog для закрытия. Если он истечет; Все отлично. Нажатие на отмену или пропустить выйдет из диалогового окна, но окно остается навсегда замороженным на экране (возвращается поток управления).wxpython: destroy cancel 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 питон v2.7.10

ответ

0

Это классический пример LongRunningTask: Ваш while цикл будет съедать все время не используется для обработки событий. Когда события начинают накапливаться, графический интерфейс становится невосприимчивым, и wxPython больше не может обрабатывать какие-либо события во времени (или обрабатывать вызовы на wx.Yield(), если на то пошло).

Решение этой проблемы заключается в том, чтобы помещать задачи блокировки событий/длинных запусков в отдельный поток и переходить в поточный режим GUI с помощью e. г. wx.CallAfter когда работа сделан.

Изучите последний пример в приведенной выше ссылке, Easiest Example *ever* :), чтобы получить представление о том, как это сделать.

+0

Это не решит проблему. После выхода из цикла диалог не будет уничтожен. Использование ЦП в цикле не имеет значения. – whitey04

+0

Понятно, что ваш пример работает для меня с той же самой ** конфигурацией, что и ваша (вещи Python 32 бит, Win7 64 бит) без малейших изменений. Даже изменения, предложенные @RobinDunn, не нужны. – nepix32

1

Возможно, это зависит от платформы, но вызывает функцию Progress после возврата MainLoop - это красный флаг для меня. Окна верхнего уровня не уничтожаются при вызове их метода Destroy, вместо этого они добавляются в ожидающую очередь удаления, которая обрабатывается позже в цикле событий.

Попробуйте поместить вызов Process перед вызовом MainLoop и убрать звонок до wx.Yield после Destroy. Это работает для меня на OSX и Phoenix.

0

Ответы 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().

 Смежные вопросы

  • Нет связанных вопросов^_^