Search code examples
python-3.xwxpythonapache-phoenix

how to suspend execution of a function


I would like to play with 3 buttons. I have to pause the execution of my function and restart the execution where it stopped(unpause). I must also put stop the execution of my function and restart the execution from the start. the cancel button must also stop the execution like stop. PyprogressDialog must disappear after a button (any button) set press.thank

import wx
import time
class PyProgressDemo(wx.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        self.panel = wx.Panel(self, -1)

        self.startbutton = wx.Button(self.panel, -1, "Start with PyProgress!")
        self.pausebutton = wx.Button(self.panel, -1, "Pause/Unpause PyProgress!")
        self.stopbutton = wx.Button(self.panel, -1, "stop all thing")

        self.startbutton.Bind(wx.EVT_BUTTON, self.onButton)
        self.pausebutton.Bind(wx.EVT_BUTTON, self.onPause)
        self.stopbutton.Bind(wx.EVT_BUTTON, self.onStop)

        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(self.startbutton)
        vbox.Add(self.pausebutton)
        vbox.Add(self.stopbutton)

        self.panel.SetSizer(vbox)
        self.Show()

        import threading
        self.shutdown_event = threading.Event()

    def activity(self):
        while not self.shutdown_event.is_set():
            for i in range(10):
                print (i)
                time.sleep(1)
                if self.shutdown_event.is_set():
                    break

            print("stop")
            self.keepGoing = True
        self.shutdown_event.set()

    def onButton(self, event):
        import threading
        threading.Thread(target = self.activity).start()

        self.dlg = wx.ProgressDialog('title', 'Some thing in progresse...', 
                                     style= wx.PD_ELAPSED_TIME 
                                     | wx.PD_CAN_ABORT)      

        self.keepGoing = False
        while self.keepGoing == False:
            wx.MilliSleep(30)
            keepGoing = self.dlg.Pulse()
        self.dlg.Destroy()

    def onPause(self, event):
        #pause/unpause
        pass

    def onStop(self, event):
        #and wx.PD_CAN_ABORT
        self.shutdown_event.set()

app = wx.App()
prog = PyProgressDemo(None)
app.MainLoop()


Solution

  • Here is a simple example that will open a progress dialog and start a simulated task when the button is clicked. When the cancel button is clicked the progress dialog will close and the long running task will stop. When the resume button is clicked it will re-open the progress dialog and re-start the long running task.

    import wx, traceback
    
    
    class Mainframe(wx.Frame):
        def __init__(self):
            super().__init__(None)
            self.btn = wx.Button(self, label="Start")
            self.btn.Bind(wx.EVT_BUTTON, self.on_btn)
            # progress tracks the completion percent
            self._progress = 0
            self._task_running = False
            self.dialog = None  # type: wx.ProgressDialog
            self.CenterOnScreen(wx.BOTH)
            self.Show()
            self.poll()
    
        def on_btn(self, evt):
            # is there a dialog already opened?
            if not self.dialog:
                # create a progress dialog with a cancel button
                self.dialog = wx.ProgressDialog("title", "message", 100, self, wx.PD_CAN_ABORT)
                self.dialog.Show()
                self.btn.SetLabel("Running")
                self.start_long_running_task()
    
        def start_long_running_task(self):
            if not self._task_running:
                print("starting long running task")
                self._task_running = True
                self.long_running_task()
    
        def long_running_task(self):
            """ this method simulates a long-running task,
            normally it would be run in a separate thread so as not to block the UI"""
            if not self:
                return  # the frame was closed
    
            if self.dialog:
                # increment the progress percent
                self._progress += 1
                if self._progress > 100:
                    self._progress = 0
                wx.CallLater(300, self.long_running_task)
            else:
                # the progress dialog was closed
                print("task stopped")
                self._task_running = False
    
        def poll(self):
            """ this method runs every 0.3 seconds to update the progress dialog, in an actual implementation
             self._progress would be updated by the method doing the long-running task"""
    
            if not self:
                return  # the frame was closed
            if self.dialog:
                # the cancel button was pressed, close the dialog and set the button label to 'Resume'
                if self.dialog.WasCancelled():
                    self.btn.SetLabel("Resume")
                    self.dialog.Destroy()
                else:
                    # update the progress dialog with the current percentage
                    self.dialog.Update(self._progress, "%s%% complete" % self._progress)
            wx.CallLater(300, self.poll)
    
    
    try:
        app = wx.App()
        frame = Mainframe()
        app.MainLoop()
    except:
        input(traceback.format_exc())