Issue with wxPython GUI

tarun tarundevnani at
Tue Nov 13 13:23:58 CET 2007

Thanks a lot Laszlo Nagy,

I used the following and it worked.

import time
from threading import *
import wx

# Button definitions
ID_START = wx.NewId()
ID_STOP = wx.NewId()

# Define notification event for thread completion
EVT_RESULT_ID = wx.NewId()

def EVT_RESULT(win, func):
    """Define Result Event."""
    win.Connect(-1, -1, EVT_RESULT_ID, func)

class ResultEvent(wx.PyEvent):
    """Simple event to carry arbitrary result data."""
    def __init__(self, data):
        """Init Result Event."""
        self.SetEventType(EVT_RESULT_ID) = data

# Thread class that executes processing
class WorkerThread(Thread):
    """Worker Thread Class."""
    def __init__(self, notify_window):
        """Init Worker Thread Class."""
        self._notify_window = notify_window
        self._want_abort = 0
        # This starts the thread running on creation, but you could
        # also make the GUI thread responsible for calling this

    def run(self):
        """Run Worker Thread."""
        # This is the code executing in the new thread. Simulation of
        # a long process (well, 10s here) as a simple loop - you will
        # need to structure your processing so that you periodically
        # peek at the abort variable
        for i in range(10):
            if self._want_abort:
                # Use a result of None to acknowledge the abort (of
                # course you can use whatever you'd like or even
                # a separate event type)
                wx.PostEvent(self._notify_window, ResultEvent(None))
        # Here's where the result would be returned (this is an
        # example fixed result of the number 10, but it could be
        # any Python object)
        wx.PostEvent(self._notify_window, ResultEvent(10))

    def abort(self):
        """abort worker thread."""
        # Method for use by main thread to signal an abort
        self._want_abort = 1

# GUI Frame class that spins off the worker thread
class MainFrame(wx.Frame):
    """Class MainFrame."""
    def __init__(self, parent, id):
        """Create the MainFrame."""
        wx.Frame.__init__(self, parent, id, 'Thread Test')

        # Dumb sample frame with two buttons
        wx.Button(self, ID_START, 'Start', pos=(0,0))
        wx.Button(self, ID_STOP, 'Stop', pos=(0,50))
        self.status = wx.StaticText(self, -1, '', pos=(0,100))

        self.Bind(wx.EVT_BUTTON, self.OnStart, id=ID_START)
        self.Bind(wx.EVT_BUTTON, self.OnStop, id=ID_STOP)

        # Set up event handler for any worker thread results

        # And indicate we don't have a worker thread yet
        self.worker = None

    def OnStart(self, event):
        """Start Computation."""
        # Trigger the worker thread unless it's already busy
        if not self.worker:
            self.status.SetLabel('Starting computation')
            self.worker = WorkerThread(self)

    def OnStop(self, event):
        """Stop Computation."""
        # Flag the worker thread to stop if running
        if self.worker:
            self.status.SetLabel('Trying to abort computation')

    def OnResult(self, event):
        """Show Result status."""
        if is None:
            # Thread aborted (using our convention of None return)
            self.status.SetLabel('Computation aborted')
            # Process results here
            self.status.SetLabel('Computation Result: %s' %
        # In either event, the worker is done
        self.worker = None

class MainApp(wx.App):
    """Class Main App."""
    def OnInit(self):
        """Init Main App."""
        self.frame = MainFrame(None, -1)
        return True

if __name__ == '__main__':
    app = MainApp(0)

Thanks & Regards,

On 11/13/07, Laszlo Nagy <gandalf at> wrote:
> tarun írta:
> > Hi Laszlo Nagy,
> >
> > Thanks a lot.
> > But the issue over here is that how will the child thread acknowledge
> > the main thread that it has completed its task. For this I'll have to
> > set some flag in the child thread and poll for it in the main thread.
> > This will create a problem.
> What kind of problem, can you explain? Supposing your child (worker)
> thread created the output, I would do it this way (untested):
> class Child(threading.Thread):
>    def __init__(self,output):
>       self.stop_requested = threading.Event()
>       self.stopped = threading.Event()
>       self.output = output
>       ....
>    def run(self):
>       try:
>           while not self.stop_requested.isSet():
>                # put your algorithm here
>                ....
>                # but check periodically if you need to abort the job.
>                if self.stop_requested.isSet():
>                   break
>                ...
>                # when you have data, put into the output queue
>                self.output.put( your_output )
>       finally:
>          self.stopped.set()
> -- And then, from the main thread, create the worker:
> self.queue = Queue()
> self.child = Child(self.queue)
> -- wxApp.OnIdle:
> if not self.queue.empty():
>    data = self.queue.get()
>    # display your data here, for example add to a text control.
> if self.child.stopped.isSet():
>    add_log("Job compete") # tell the user what is going on
> And finally, you can have a button for stopping the script:
> def OnClick(self,event):
>    self.child.stop_requested.set()
>    add_log("stopping worker thread....")   # tell the user what is going
> on
> > Any alternatives??
> First you should tell us what is the problem with using two threads.
> Regards,
>   Laszlo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the Python-list mailing list