How to change/set StaticText label from outside function

1,574 views
Skip to first unread message

xre...@gmail.com

unread,
Oct 24, 2013, 9:27:51 AM10/24/13
to wxpytho...@googlegroups.com
I am new to Python programming, and nowhere up to speed in really understanding more complicated Classes.

I have a code below, where most of it has been generated by a GUI designer (Boa Constructor). 
There are no problems with generated wx Python code for GUI that is contained within a Class.

I have a problem with outside function, where I need to change a StaticText label, Static text is defined in the GUI Class.

Outside function def Rpccallfunction(value): Must stay outside the Class as it is called from another remote application,
and this can not be changed.

Ideally, I would not want to change any of the sample code listed below.
I would only like to know what would be needed in front (????)  of the statement,  ????.staticText1.SetLabel(str(value)) 
to change staticText1 label from a function Rpccallfunction(value): .

All advice would be appreciated.

Regards
John




import wx

import time

def create(parent):
    return Frame1(parent)

[wxID_FRAME1, wxID_FRAME1PANEL1, wxID_FRAME1STATICTEXT1, 
] = [wx.NewId() for _init_ctrls in range(3)]

[wxID_FRAME1TIMER1] = [wx.NewId() for _init_utils in range(1)]

class Frame1(wx.Frame):
    def _init_utils(self):
        # generated method, don't edit
        self.timer1 = wx.Timer(id=wxID_FRAME1TIMER1, owner=self)
        self.timer1.Start(1000)
        self.Bind(wx.EVT_TIMER, self.OnTimer1Timer, id=wxID_FRAME1TIMER1)

    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
              pos=wx.Point(466, 32), size=wx.Size(1297, 987),
              style=wx.STATIC_BORDER | wx.DEFAULT_FRAME_STYLE, title='Frame1')
        self._init_utils()
        self.SetClientSize(wx.Size(1281, 949))
        self.SetBackgroundColour(wx.Colour(192, 192, 192))

        self.panel1 = wx.Panel(id=wxID_FRAME1PANEL1, name='panel1', parent=self,
              pos=wx.Point(112, 136), size=wx.Size(928, 544),
              style=wx.TAB_TRAVERSAL)

        self.staticText1 = wx.StaticText(id=wxID_FRAME1STATICTEXT1, label=u'A', #Initial Text label is 'A'
              name='staticText1', parent=self.panel1, pos=wx.Point(112, 16),
              size=wx.Size(18, 31), style=wx.SIMPLE_BORDER)
        self.staticText1.SetBackgroundColour(wx.Colour(0, 255, 0))
        self.staticText1.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD,
              False, u'Tahoma'))

    def __init__(self, parent):
        self._init_ctrls(parent)
     
        
        
    def OnTimer1Timer(self, event): #Example Timer event that changes text label to 'test', THIS WORKS OK.
        
        self.staticText1.SetLabel('test') 
        
        self.Update()
    
        event.Skip()    


if __name__ == '__main__':
    app = wx.PySimpleApp()
    frame = create(None)
    frame.Show()
    app.MainLoop()
    
def startup():
    global frame
    frame = create(None)
    frame.Show()
    
def Rpccallfunction(value): #This function is called by remote RF node with argument 'value'.
    
    #Now I want to set staticText1 label = value.
    # Don't know what ???? should be for this statement to work.
    
    #????.staticText1.SetLabel(str(value))
    #????.Update()
     
    pass
   
    


Tim Roberts

unread,
Oct 24, 2013, 12:58:31 PM10/24/13
to wxpytho...@googlegroups.com
xre...@gmail.com wrote:
>
> I have a problem with outside function, where I need to change a
> StaticText label, Static text is defined in the GUI Class.
>
> Outside function def Rpccallfunction(value): Must stay outside the
> Class as it is called from another remote application,
> and this can not be changed.
>
> Ideally, I would not want to change any of the sample code listed below.
> I would only like to know what would be needed in front (????) of the
> statement, ????.staticText1.SetLabel(str(value))
> to change staticText1 label from a function Rpccallfunction(value): .

Well, your main window is stored in the global object called "frame", so
that's the basic access point.

Unfortunately, it isn't that straightforward. The problem is you cannot
mess with GUI components from any thread other than the one that created
the window. That's an operating system restriction, not a wx
restriction. Since your main thread is busy running your message loop,
it must be the case that Rpccallfunction is being called from a
different thread.

So, you are going to have to do something in Rpccallfunction that
triggers an action within the GUI. There are several alternatives. You
could, for example, have Rpccallfunction put a request on a queue, then
have your timer function check for those requests periodically. The
timer callback will run on the correct thread.

Alternatively, you could have Rpccallfunction use CallAfter.:

class Frame1(wx.Frame):
....
def UpdateLabel( self, value ):
self.staticText1.SetLabel( value )

def Rpccallfunction(value):
wx.CallAfter( frame.UpdateLabel, str(value) )

--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

xre...@gmail.com

unread,
Oct 24, 2013, 5:04:14 PM10/24/13
to wxpytho...@googlegroups.com
Thanks Very Much Tim,

>Alternatively, you could have Rpccallfunction use CallAfter.: 

>class Frame1(wx.Frame): 
>   .... 
>   def UpdateLabel( self, value ): 
>       self.staticText1.SetLabel( value ) 

>def Rpccallfunction(value): 
>  wx.CallAfter( frame.UpdateLabel, str(value) ) 

CallAfter has done the trick. 

Best Regards
John
Reply all
Reply to author
Forward
0 new messages