Вы можете использовать модуль _thread для создания нового потока и pubsub для управления связью между потоками.Один из способов сделать это показан ниже.Я добавил несколько комментариев к коду.
import wx
import time
import _thread
from pubsub import pub
seconds = 10
class MyFrame(wx.Frame):
def __init__(self):
"""
Just a button to start counting
"""
super().__init__(None, title='Counting until...')
self.panel = wx.Panel(self)
self.button = wx.Button(self.panel, label='Count', pos=(50, 50))
self.button.Bind(wx.EVT_BUTTON, self.OnCount)
## This will subscribe the window to the message 'Finish counting'.
## Thus, everytime the message is broadcast the self.Pass method
## will be executed.
pub.subscribe(self.Pass, 'Finish counting')
def OnCount(self, event):
dlg = wx.MessageDialog(None, "Do you want to count?",
style=wx.YES_NO|wx.ICON_QUESTION)
if dlg.ShowModal() == wx.ID_YES:
self.count()
else:
pass
def count(self):
## Creates and starts a new thread that will execute the self.wait
## method. Notice that the thread is started before the ProgressDialog
## because the ProgressDialog will keep the main thread busy
_thread.start_new_thread(self.wait, (seconds,))
## ProgressDialog that will keep running until maxV is reached or
## until self.keepGoing is set to False
maxV = 100
dlg = wx.ProgressDialog("Progress dialog example",
"An informative message",
maximum = maxV,
parent=self,
style = 0
| wx.PD_APP_MODAL
#| wx.PD_CAN_ABORT
#| wx.PD_CAN_SKIP
| wx.PD_ELAPSED_TIME
#| wx.PD_ESTIMATED_TIME
#| wx.PD_REMAINING_TIME
#| wx.PD_AUTO_HIDE
)
self.keepGoing = True
count = 0
while self.keepGoing and count < maxV:
count += 1
wx.MilliSleep(250)
wx.SafeYield()
(keepGoing, skip) = dlg.Update(count)
dlg.Destroy()
def wait(self, secs):
## This is the function that is executed by the new thread
## when it finishs the wx.CallAfter method broadcast the message
## 'Finish counting' that triggers self.Pass as mentioned above.
time.sleep(secs)
wx.CallAfter(pub.sendMessage, 'Finish counting')
def Pass(self):
## Changes self.keepGoing to false so the ProgressDialog is destroyed.
self.keepGoing = False
if __name__ == "__main__":
app = wx.App()
frame = MyFrame()
frame.Show()
app.MainLoop()
По поводу наличия индикатора в диалоговом окне с просьбой продолжить.Это можно сделать, но вам нужно создать свое диалоговое окно и, вероятно, использовать wx.Gauge
вместо wx.ProgressDialog
.Также наиболее вероятно, что вы захотите, чтобы это пользовательское окно было модальным (заморозьте все остальные окна в программе, чтобы пользователь дождался завершения работы функции в потоке).Для этого добавьте следующий метод в класс настраиваемого диалогового окна
def ShowModal(self):
"""
wx.Dialog behavior
"""
self._disabler = wx.WindowDisabler(self)
self.Show()
self.eventLoop = wx.GUIEventLoop()
self.eventLoop.Run()
и отобразите настраиваемое диалоговое окно так же, как в обычном режиме wx.Dialog
, custom_dialog.ShowModal()