I have a GUI application, running in my main thread, and some children thread doing stuff in the background. I binded the close button to a method, to do stuff before closing the software, but I can't figure out how to stop the children threads
self.Bind(wx.EVT_CLOSE, self.onCloseFrame)
def onCloseFrame(self, event):
do_stuff()
# stop threads here
self.Destroy()
Is there a way to do that?
This is a test I mocked up for something.
It's a bit more complicated than it needs to be, because I wanted multiple progress indicators but you should be able to get the gist of it.
Include a termination function and trigger it, if you wish to end the thread before it has naturally finished.
In this instance, the thread times out after a minute but it could be doing whatever.
Click Start
for as many threads as you wish to have running simultaneously.
import time
import wx
from threading import Thread
import wx.lib.newevent
progress_event, EVT_PROGRESS_EVENT = wx.lib.newevent.NewEvent()
class ProcessingFrame(wx.Frame):
def __init__(self, title, parent=None):
wx.Frame.__init__(self, parent=parent, title=title)
panel = wx.Panel(self)
self.parent = parent
self.btn = wx.Button(panel,label='Stop processing', size=(200,30), pos=(10,10))
self.btn.Bind(wx.EVT_BUTTON, self.OnExit)
self.progress = wx.Gauge(panel,size=(240,10), pos=(10,50), range=60)
self.process = wx.TextCtrl(panel,size = (200,250), pos=(10,100), style = wx.TE_MULTILINE)
#Bind to the progress event issued by the thread
self.Bind(EVT_PROGRESS_EVENT, self.OnProgress)
#Bind to Exit on frame close
self.Bind(wx.EVT_CLOSE, self.OnExit)
self.Show()
self.mythread = TestThread(self)
def OnProgress(self, event):
self.progress.SetValue(event.count)
self.process.write("Checking process: "+event.process+"\n")
self.Refresh()
if event.count >= 60:
self.OnExit(None)
def OnExit(self, event):
if self.mythread.isAlive():
self.mythread.terminate() # Shutdown the thread
self.mythread.join() # Wait for it to finish
self.Destroy()
class TestThread(Thread):
def __init__(self,parent_target):
Thread.__init__(self)
self.parent = parent_target
self.stopthread = False
self.time = time.time()
self.process = 1 # Testing only - mock process id
self.start() # start the thread
def run(self):
# A loop that will run for a while then terminate
while self.stopthread == False:
curr_loop = int(time.time() - self.time)
self.process += 10 # Testing only - mock process id
if curr_loop <= 60: # Update progress bar
time.sleep(0.1)
evt = progress_event(count=curr_loop,process=str(self.process))
#Send back current count for the progress bar
try:
wx.PostEvent(self.parent, evt)
except: # The parent frame has probably been destroyed
self.terminate()
def terminate(self):
self.stopthread = True
class MyPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.text_count = 0
self.parent=parent
btn_start = wx.Button(self, wx.ID_ANY, label='Start Long running process', size=(180,30), pos=(10,10))
btn_test = wx.Button(self, wx.ID_ANY, label='Is the GUI still active?', size=(180,30), pos=(10,50))
self.txt = wx.TextCtrl(self, wx.ID_ANY, style= wx.TE_MULTILINE, pos=(10,90),size=(400,100))
btn_end = wx.Button(self, wx.ID_ANY, label='Stop All', size=(100,30), pos=(10,200))
btn_start.Bind(wx.EVT_BUTTON, self.Start_Process)
btn_test.Bind(wx.EVT_BUTTON, self.ActiveText)
btn_end.Bind(wx.EVT_BUTTON, self.End_AllProcesses)
self.activeframes = [] # 1 per live process
def Start_Process(self, event):
#thread_count = active_count()
thread_count = len(self.activeframes) + 1
self.activeframes.append(ProcessingFrame(title='Threaded Task '+str(thread_count), parent=self))
def End_AllProcesses(self, event):
while len(self.activeframes) > 0:
try:
self.activeframes[-1].OnExit(None)
self.activeframes.pop(-1)
except: # process may have finished or been stopped individually
self.activeframes.pop(-1)
def ActiveText(self,event):
self.text_count += 1
txt = "Gui is still active " + str(self.text_count)+"\n"
self.txt.write(txt)
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title='Main Frame', size=(600,400))
panel = MyPanel(self)
self.Show()
if __name__ == '__main__':
app = wx.App(False)
frame = MainFrame()
app.MainLoop()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.