wxPython and sharing objects between windows
Question: I've been working with python for a while now and am just starting to learn
wxPython. After creating a few little programs, I'm having difficulty
understanding how to create objects that can be shared between dialogs.

Here's some code as an example (apologies for the length - I've tried to
trim):

    
    
    import wx
    
    class ExampleFrame(wx.Frame):
        """The main GUI"""
        def __init__(self, parent, id, title):
            wx.Frame.__init__(self, parent, id, title, size=(200,75))
            mainSizer = wx.BoxSizer(wx.VERTICAL)
    
            # Setup buttons
            buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
            playerButton = wx.Button(self, wx.ID_ANY, "Player number", wx.DefaultPosition, wx.DefaultSize, 0)
            buttonSizer.Add(playerButton, 1, wx.ALL | wx.EXPAND, 0)
            nameButton = wx.Button(self, wx.ID_ANY, "Player name", wx.DefaultPosition, wx.DefaultSize, 0)
            buttonSizer.Add(nameButton, 1, wx.ALL | wx.EXPAND, 0)
    
            # Complete layout and add statusbar
            mainSizer.Add(buttonSizer, 1, wx.EXPAND, 5)
            self.SetSizer(mainSizer)
            self.Layout()
    
            # Deal with the events
            playerButton.Bind(wx.EVT_BUTTON, self.playerButtonEvent)
            nameButton.Bind(wx.EVT_BUTTON, self.nameButtonEvent)
            self.Show(True)
            return
    
        def playerButtonEvent(self, event):
            """Displays the number of game players"""
            playerDialog = PlayerDialogWindow(None, -1, "Player")
            playerDialogResult = playerDialog.ShowModal() 
            playerDialog.Destroy()
            return
    
        def nameButtonEvent(self, event):
            """Displays the names of game players"""
            nameDialog = NameDialogWindow(None, -1, "Name")
            nameDialogResult = nameDialog.ShowModal() 
            nameDialog.Destroy()
            return
    
    class PlayerDialogWindow(wx.Dialog):
        """Displays the player number"""
        def __init__(self, parent, id, title):
            wx.Dialog.__init__(self, parent, id, title, size=(200,120))
    
            # Setup layout items
            self.SetAutoLayout(True)
            mainSizer = wx.BoxSizer(wx.VERTICAL)
            dialogPanel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
            dialogSizer = wx.BoxSizer(wx.VERTICAL)
    
            # Display player number
            playerNumber = "Player number is %i" % gamePlayer.number
            newLabel = wx.StaticText(dialogPanel, wx.ID_ANY, playerNumber, wx.DefaultPosition, wx.DefaultSize, 0)
            dialogSizer.Add(newLabel, 0, wx.ALL | wx.EXPAND, 5)
    
            # Setup buttons
            buttonSizer = wx.StdDialogButtonSizer()
            okButton = wx.Button(dialogPanel, wx.ID_OK)
            buttonSizer.AddButton(okButton)
            buttonSizer.Realize()
            dialogSizer.Add(buttonSizer, 1, wx.EXPAND, 5)
    
            # Complete layout
            dialogPanel.SetSizer(dialogSizer)
            dialogPanel.Layout()
            dialogSizer.Fit(dialogPanel)
            mainSizer.Add(dialogPanel, 1, wx.ALL | wx.EXPAND, 5)
            self.SetSizer(mainSizer)
            self.Layout()
    
            # Deal with the button events
            okButton.Bind(wx.EVT_BUTTON, self.okClick)
            return
    
        def okClick(self, event):
            """Deals with the user clicking the ok button"""
            self.EndModal(wx.ID_OK)
            return 
    
    class NameDialogWindow(wx.Dialog):
        """Displays the player name"""
        def __init__(self, parent, id, title):
            wx.Dialog.__init__(self, parent, id, title, size=(200,120))
    
            # Setup layout items
            self.SetAutoLayout(True)
            mainSizer = wx.BoxSizer(wx.VERTICAL)
            dialogPanel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
            dialogSizer = wx.BoxSizer(wx.VERTICAL)
    
            # Display player number
            playerNumber = "Player name is %s" % gamePlayer.name
            newLabel = wx.StaticText(dialogPanel, wx.ID_ANY, playerNumber, wx.DefaultPosition, wx.DefaultSize, 0)
            dialogSizer.Add(newLabel, 0, wx.ALL | wx.EXPAND, 5)
    
            # Setup buttons
            buttonSizer = wx.StdDialogButtonSizer()
            okButton = wx.Button(dialogPanel, wx.ID_OK)
            buttonSizer.AddButton(okButton)
            buttonSizer.Realize()
            dialogSizer.Add(buttonSizer, 1, wx.EXPAND, 5)
    
            # Complete layout
            dialogPanel.SetSizer(dialogSizer)
            dialogPanel.Layout()
            dialogSizer.Fit(dialogPanel)
            mainSizer.Add(dialogPanel, 1, wx.ALL | wx.EXPAND, 5)
            self.SetSizer(mainSizer)
            self.Layout()
    
            # Deal with the button events
            okButton.Bind(wx.EVT_BUTTON, self.okClick)
            return
    
        def okClick(self, event):
            """Deals with the user clicking the ok button"""
            self.EndModal(wx.ID_OK)
            return 
    
    class Player(object):
        """A game player"""
        def __init__(self, number, name):
            self.number = number
            self.name = name
            return
    
    def main():
        # Start GUI
        global gamePlayer
        gamePlayer = Player(1, "John Smith")
        app = wx.App(redirect=False)
        frame = ExampleFrame(None, -1, "Example frame")
        frame.Show(True)
        app.MainLoop()
        return 0
    
    if __name__ == '__main__':
        main()
    

So, I want both of the dialogs to access the gamePlayer object. At the moment,
the only way I can think of doing it is to create the gamePlayer object as a
global object, but these are normally frowned upon - is there a better way to
do this?

There is a method of passing objects in event bindings in [this
question](http://stackoverflow.com/questions/173687?sort=votes), but it
doesn't feel quite right.

Is learning to implement the MVC pattern the way forward here?

Thanks.


Answer: You can pass a gamePlayer object to `__init__` as another argument.

    
    
    def __init__(self, parent, id, title, gamePlayer ):
        ...etc...
    

In the long run, this isn't ideal.

You should separate building an empty panel from loading that panel with data.
The empty panel is one thing, populating it with data from the model is
unrelated.

Populating a frame with data is where you must be given the gamePlayer object
which will be used to update the various display widgets.

I'd suggest you look at the Document-View framework for guidance on this.
<http://docs.wxwidgets.org/stable/wx_docviewoverview.html#docviewoverview>.
Unfortunately, there aren't any good Python examples of this, so it can be
confusing to convert from the C++ code to Python.

Ultimately, you have a "document" which is the main object ("gamePlayer") that
is being displayed. Each Frame is a view of that document.

