Creating a Boa version of Wiki Example

2004-01-20
2004-02-15
  • Karl M Jewsbury

    Karl M Jewsbury - 2004-01-20

    I have been trying to use the Wiki Example of threading in Boa with no Sucess, the Events/Resutls appeared to get lost and are never reported back to the GIU.  I am trying to get this working so I can create a GUI front end to my Python Scripts which I intend to place in the Thread.

    Any help or suggestions would be great

    Karl

    The version is the Wiki example.

    import time
    from threading import *
    from wxPython.wx import *

    # Button definitions
    ID_START = wxNewId()
    ID_STOP  = wxNewId()

    # Define notification event for thread completion
    EVT_RESULT_ID = wxNewId()

    def EVT_RESULT(win, func):
        print func
        win.Connect(-1, -1, EVT_RESULT_ID, func)

    class ResultEvent(wxPyEvent):
        """Simple event to carry arbitrary result data"""

        def __init__(self, data):
            wxPyEvent.__init__(self)
            self.SetEventType(EVT_RESULT_ID)
            self.data = data

    # Thread class that executes processing
    class WorkerThread(Thread):
        def __init__(self, notify_window):
            Thread.__init__(self)
            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
            self.start()

        def run(self):
            # 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):
                time.sleep(1)
                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)
                    wxPostEvent(self._notify_window,ResultEvent(None))
                    return
                # 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)
            wxPostEvent(self._notify_window,ResultEvent(10))

        def abort(self):
            # 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(wxFrame):
        def __init__(self, parent, id):
                wxFrame.__init__(self,parent,id,'Thread Test')

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

                EVT_BUTTON(self,ID_START,self.OnStart)
                EVT_BUTTON(self,ID_STOP,self.OnStop)

                # Set up event handler for any worker thread results
                EVT_RESULT(self,self.OnResult)
                # And indicate we don't have a worker thread yet
                self.worker = None
               
           
        def OnStart(self, event):
                # 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):
                # Flag the worker thread to stop if running
                if self.worker:
                    self.status.SetLabel('Trying to abort computation')
                    self.worker.abort()

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

    class MainApp(wxApp):
        def OnInit(self):
                self.frame = MainFrame(None,-1)
                self.frame.Show(true)
                self.SetTopWindow(self.frame)
                return true

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

    I tried to add this to a basic Boa script as shown below

    #Boa:Frame:wxFrame1
    import time
    from wxPython.wx import *
    #from datetime import tzinfo, timedelta, datetime, date, time
    from threading import *
    output ='NothingYet'
    id= -1
    ID_START = wxNewId()
    ID_STOP  = wxNewId()
    # Define notification event for thread completion
    EVT_RESULT_ID = wxNewId()
    print "start"
    def EVT_RESULT(self, func):
        #print "evt_result def"
        #print func
        self.Connect(-1, -1, EVT_RESULT_ID, func)
       
    class ResultEvent(wxPyEvent):
        """Simple event to carry arbitrary result data"""
        def __init__(self, data):
            #print "ResultEvent"
            #print swxPyEvent.__init__(self)
            wxPyEvent.__init__(self)
            self.SetEventType(EVT_RESULT_ID)
            self.data = data
    print "end"
    # Thread class that executes processing
    class WorkerThread(Thread):
        def __init__(self, notify_window):
            Thread.__init__(self)
            print notify_window
            print self
            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
            self.start()

        def run(self):
            # 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):
                time.sleep(1)
                #self.staticText8.SetLabel('go')
                print i
                print self._want_abort
                #print thread
                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)
                    print "Abort Exercised"
                    print self._notify_window
                    wxPostEvent(self._notify_window,ResultEvent(0))
                    return
            # 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)
            print "Thead Ending 10 seconds are up"
            print self._notify_window
            wxPostEvent(self._notify_window,ResultEvent(10))
                  
        def abort(self):
            # Method for use by main thread to signal an abort
            print "Abort option Run"
            self._want_abort = 1

    def create(parent):
        return wxFrame1(parent)

    [wxID_WXFRAME1, wxID_WXFRAME1BUTTON1, wxID_WXFRAME1BUTTON2,
    wxID_WXFRAME1PANEL1, wxID_WXFRAME1STATICTEXT1, wxID_WXFRAME1STATICTEXT2,
    wxID_WXFRAME1STATICTEXT3, wxID_WXFRAME1STATICTEXT4, wxID_WXFRAME1STATICTEXT5,
    wxID_WXFRAME1STATICTEXT6, wxID_WXFRAME1STATICTEXT7, wxID_WXFRAME1STATICTEXT8,
    wxID_WXFRAME1STATUSBAR1,
    ] = map(lambda _init_ctrls: wxNewId(), range(13))

    [wxID_WXFRAME1MNUFILEITEMS0] = map(lambda _init_coll_mnuFile_Items: wxNewId(), range(1))

    [wxID_WXFRAME1MNUHELPITEMS0] = map(lambda _init_coll_mnuhelp_Items: wxNewId(), range(1))

    class wxFrame1(wxFrame):
        def _init_coll_mnuhelp_Items(self, parent):
            # generated method, don't edit

            parent.Append(helpString=u"'Display General Information About DW6000'",
                  id=wxID_WXFRAME1MNUHELPITEMS0, item=u'About', kind=wxITEM_NORMAL)
            EVT_MENU(self, wxID_WXFRAME1MNUHELPITEMS0, self.OnMnuhelpitems0Menu)

        def _init_coll_mnuFile_Items(self, parent):
            # generated method, don't edit

            parent.Append(helpString=u"'File Menu'", id=wxID_WXFRAME1MNUFILEITEMS0,
                  item=u'File', kind=wxITEM_NORMAL)
            EVT_MENU(self, wxID_WXFRAME1MNUFILEITEMS0, self.OnMnufileitems0Menu)

        def _init_coll_menuBar1_Menus(self, parent):
            # generated method, don't edit

            parent.Append(menu=self.mnuFile, title=u'File')
            parent.Append(menu=self.mnuhelp, title=u'Help')

        def _init_coll_statusBar1_Fields(self, parent):
            # generated method, don't edit
            parent.SetFieldsCount(1)

            parent.SetStatusText(i=0, text='Fields0')

            parent.SetStatusWidths([-1])

        def _init_utils(self):
            # generated method, don't edit
            self.mnuFile = wxMenu(title=u'File')
            self._init_coll_mnuFile_Items(self.mnuFile)

            self.mnuhelp = wxMenu(title=u'Help')
            self._init_coll_mnuhelp_Items(self.mnuhelp)

            self.menuBar1 = wxMenuBar()

            self._init_coll_menuBar1_Menus(self.menuBar1)

        def _init_ctrls(self, prnt):
            # generated method, don't edit
            wxFrame.__init__(self, id=wxID_WXFRAME1, name='', parent=prnt,
                  pos=wxPoint(455, 303), size=wxSize(678, 250),
                  style=wxDEFAULT_FRAME_STYLE, title=u'DW6000')
            self._init_utils()
            self.SetClientSize(wxSize(670, 223))
            self.SetMenuBar(self.menuBar1)

            self.statusBar1 = wxStatusBar(id=wxID_WXFRAME1STATUSBAR1,
                  name='statusBar1', parent=self, style=0)
            self.statusBar1.SetPosition(wxPoint(0, 184))
            self.statusBar1.SetSize(wxSize(502, 20))
            self.statusBar1.SetHelpText(u"'Status Bar'")
            self.statusBar1.SetStatusText(u'')
            self.statusBar1.SetLabel(u'Status Bar')
            self._init_coll_statusBar1_Fields(self.statusBar1)
            self.SetStatusBar(self.statusBar1)

            self.button1 = wxButton(id=wxID_WXFRAME1BUTTON1, label=u'Start',
                  name='button1', parent=self, pos=wxPoint(8, 8), size=wxSize(75,
                  23), style=0)
            self.button1.SetHelpText(u'Start Monitoring DW 6000')
            EVT_BUTTON(self.button1, wxID_WXFRAME1BUTTON1, self.OnButton1Button)
            EVT_LEFT_DOWN(self.button1, self.OnButton1LeftDown)

            self.button2 = wxButton(id=wxID_WXFRAME1BUTTON2, label=u'Stop',
                  name='button2', parent=self, pos=wxPoint(8, 40), size=wxSize(75,
                  23), style=0)
            EVT_LEFT_DOWN(self.button2, self.OnButton2LeftDown)

            self.panel1 = wxPanel(id=wxID_WXFRAME1PANEL1, name='panel1',
                  parent=self, pos=wxPoint(96, 8), size=wxSize(232, 100),
                  style=wxTAB_TRAVERSAL)

            self.staticText1 = wxStaticText(id=wxID_WXFRAME1STATICTEXT1,
                  label=u'Start Date/Time', name='staticText1', parent=self.panel1,
                  pos=wxPoint(8, 8), size=wxSize(76, 13), style=0)

            self.staticText2 = wxStaticText(id=wxID_WXFRAME1STATICTEXT2,
                  label='staticText2', name='staticText2', parent=self.panel1,
                  pos=wxPoint(112, 8), size=wxSize(104, 13), style=0)

            self.staticText3 = wxStaticText(id=wxID_WXFRAME1STATICTEXT3,
                  label=u'Operational Time', name='staticText3', parent=self.panel1,
                  pos=wxPoint(8, 24), size=wxSize(80, 13), style=0)

            self.staticText4 = wxStaticText(id=wxID_WXFRAME1STATICTEXT4,
                  label='staticText4', name='staticText4', parent=self.panel1,
                  pos=wxPoint(112, 24), size=wxSize(104, 13), style=0)

            self.staticText5 = wxStaticText(id=wxID_WXFRAME1STATICTEXT5,
                  label=u'Poll Period', name='staticText5', parent=self.panel1,
                  pos=wxPoint(8, 40), size=wxSize(50, 13), style=0)

            self.staticText6 = wxStaticText(id=wxID_WXFRAME1STATICTEXT6,
                  label='staticText6', name='staticText6', parent=self.panel1,
                  pos=wxPoint(112, 40), size=wxSize(104, 13), style=0)

            self.staticText7 = wxStaticText(id=wxID_WXFRAME1STATICTEXT7,
                  label=u'Run Time', name='staticText7', parent=self.panel1,
                  pos=wxPoint(8, 56), size=wxSize(46, 13), style=0)

            self.staticText8 = wxStaticText(id=wxID_WXFRAME1STATICTEXT8,
                  label='staticText8', name='staticText8', parent=self.panel1,
                  pos=wxPoint(112, 56), size=wxSize(104, 13), style=0)

        def __init__(self, parent):
            #print self
            wxFrame.__init__(self,parent,id,'Thread Test')
            #wxFrame.__init__(self, id=wxID_WXFRAME1, 'Thread Test')
            # Set up event handler for any worker thread results
            #print self
            EVT_RESULT(self,self.OnResult)
            #print parent
            #print self.OnResult
            #print wxFrame.__init__(self,parent,id,'Thread Test')
            #print EVT_RESULT
            # And indicate we don't have a worker thread yet
            self.worker = None
            #print self.worker
            self._init_ctrls(parent)
            #print self

        def OnMnuhelpitems0Menu(self, event):
            event.Skip()

        def OnMnufileitems0Menu(self, event):
            event.Skip()

        def OnButton1Button(self, event):
            #now = datetime.today()
            #print 'Start Button Pressed'
            #Output = 'Start Button Pressed'
            event.Skip()

        def OnButton1LeftDown(self, event):
            print 'Start Button Pressed 1'
            self.staticText2.SetLabel('Start Button Pressed')
            self.staticText4.SetLabel('Start Button Pressed')
            self.staticText6.SetLabel('Start Button Pressed')
            self.staticText8.SetLabel('Start Button Pressed')
            # Trigger the worker thread unless it's already busy
            if not self.worker:
                self.staticText8.SetLabel('Starting Worker Thread')
                print "starting Worker Thread"
                print self
                self.worker = WorkerThread(parent)
                #print self.worker
    #        event.Skip()

        def OnButton2LeftDown(self, event):
            # Flag the worker thread to stop if running
            if self.worker:
                self.staticText8.SetLabel('Stopping Thread')
                self.worker.abort()
    #        event.Skip()
           
        def OnResult(self, event):
            print "Result"
            if event.data is None:
                # Thread aborted (using our convention of None return)
                self.staticText8.SetLabel('Thread Stopped')
            else:
                # Process results here
                self.staticText2.SetLabel('Computation Result: %s' % event.data)
            # In either event, the worker is done
            self.worker = None

     
    • Riaan Booysen

      Riaan Booysen - 2004-02-15

      I'm not even aware of a wiki example for threads.

      My stance on that is: great if it works, sorry if it doesn't.

      I personally just use wxCallAfter to communicate from threads to the main thread (in which the GUI runs)

      Riaan.

       

Log in to post a comment.