Search code examples
pythonevent-handlingwxpython

wxpython assign variable in an event handler


I would like to assign the value of a menu click to a class variable so I can use that value throughout multiple classes. Any help would be greatly appreciated!

import wx

class TrackPanel (wx.Panel):
    """"""
    def __init__(self, parent, *args, **kwargs):
        """Constructor"""
        wx.Panel.__init__(self, parent, *args, **kwargs)

        mainSizer =wx.BoxSizer(wx.VERTICAL)
        track = MasterPage.track_selected  # This is where i would like access the variable      
        title = wx.StaticText(self, wx.ID_ANY, label = track)
        mainSizer.Add(title, 0,wx.ALL | wx.EXPAND | wx.CENTER)

        self.SetSizerAndFit(mainSizer)
        self.Layout()

class MasterPage (wx.Frame):
    track_selected = ' '   
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        menubar = wx.MenuBar()
        tracksopt = wx.Menu()

        track_command = wx.MenuItem(tracksopt, wx.ID_ANY, 'Atlanta')
        tracksopt.Append(track_command)
        self.Bind(wx.EVT_MENU, self.change_track, track_command)
        track_command2 = wx.MenuItem(tracksopt, wx.ID_ANY, 'Texas')
        tracksopt.Append(track_command2)
        self.Bind(wx.EVT_MENU, self.change_track, track_command2)        

        menubar.Append(tracksopt, '&Tracks')
        self.SetMenuBar(menubar)                       

    def change_track (self, event):
        """Changes the tack_selected variable based on the menu item picked"""
        id_selected = event.GetId()
        obj = event.GetEventObject()
        track_id= obj.GetLabel(id_selected)
        MasterPage.track_selected = track_id

Solution

  • You must create a link to the master in the tracker in order for the tracker to access values in the master.

    import wx
    
    class Track (wx.Frame):
        def __init__(self, link):
            wx.Frame.__init__(self, None)
            self.link = link
            self.tc = wx.TextCtrl(self, style=wx.TE_MULTILINE)
            self.bt = wx.Button(self, label="tracker (push to read master)")
            self.bt.Bind(wx.EVT_BUTTON, self.on_read_master)
            self.Title = 'Tracker'
            sz_1 = wx.BoxSizer(wx.HORIZONTAL)
            sz_2 = wx.BoxSizer(wx.VERTICAL)
            sz_2.Add(self.tc, 1, wx.EXPAND, 0)
            sz_2.Add(self.bt, 0, wx.EXPAND, 0)
            sz_1.Add(sz_2, 1, wx.EXPAND, 0)
            self.SetSizer(sz_1)
            self.Layout()
            self.SetSize((250, 100))
    
        def on_read_master(self, evt):
            self.tc.SetValue(self.link.track_selected)   # here you access the variable)
    
    class Master(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None)
            self.track_selected = '0'
            self.tc = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE)
            self.bt = wx.Button(self, wx.ID_ANY, "master (push to send)")
            self.bt.Bind(wx.EVT_BUTTON, self.change_track)
            self.Title = 'Master'
            self.tc.SetValue('enter value to be read by the tracker')
            sz_1 = wx.BoxSizer(wx.HORIZONTAL)
            sz_2 = wx.BoxSizer(wx.VERTICAL)
            sz_2.Add(self.tc, 1, wx.EXPAND, 0)
            sz_2.Add(self.bt, 0, wx.EXPAND, 0)
            sz_1.Add(sz_2, 1, wx.EXPAND, 0)
            self.SetSizer(sz_1)
            self.Layout()
            self.SetSize((250, 100))
    
        def change_track (self, evt):
            """Changes variable based on text entered"""
            self.track_selected = self.tc.GetValue()
    
    if __name__ == "__main__":
        app = wx.App(0)
        master =  Master()
        track = Track(master)
        master.Show()
        track.Show()
        app.MainLoop()
    

    This is the fast and dirty method I generally use. If you want something more sophisticated, there is a dedicated library to pass messages between frames: pubsub. A good tutorial of how to use it can be found in the Mike Driscoll blog