How to structure my code?
Question: Edit: I just combined all my questions to one big question: [Need tutorial for
menubar-handling & panel-
building](http://stackoverflow.com/questions/12604139/need-tutorial-for-
menubar-handling-panel-building)

I have a "bigger" question: I'm new to python and I started creating a little
program -> "learning by doing" ;) My program works (it's not too big yet), but
the code is already a little confusing: I have only 1 class in it and many,
many functions, which refer to each other. So my question is: Can anyone give
me hints how I can structure my code? I think I have to create more classes...
but where? Which part of my code should I combine to a new class? Short
description about my program (what it shall do when it's done): it is a kind
of soccer//football manager game; you create a team consisting of 3 player
which different attributes, you can coach them (improve their attributes) and
play against other (computer-) teams. You can also have a look at the code and
tell me how I can structe it and in which part I should create a new class:

    
    
    # -*- coding: cp1252 -*-
    import wx
    
    class myclass(wx.Frame):
    
        def __init__(self,parent,id):
            self.title='Click Kick'
            bgcolour=(170,255,170)
    
            wx.Frame.__init__(self,parent,id,self.title,size=wx.DisplaySize())
            self.displayw=wx.DisplaySize()[0]
            self.displayh=wx.DisplaySize()[1]
    
            self.startpanel=wx.Panel(self,size=wx.DisplaySize())
            titlefont = wx.Font(10, wx.MODERN, wx.NORMAL, wx.NORMAL, False, u'Consolas')
            self.SetBackgroundColour(bgcolour)
            self.dateinewgamepanel=wx.Panel(self,size=wx.DisplaySize())
            self.dateiloadgamepanel=wx.Panel(self,size=wx.DisplaySize())
            self.teamoverviewpanel=wx.Panel(self,size=wx.DisplaySize())
            self.trainingpanel=wx.Panel(self,size=wx.DisplaySize())
            self.spielpanel=wx.Panel(self,size=wx.DisplaySize())
            self.regelnpanel=wx.Panel(self,size=wx.DisplaySize())
            self.infopanel=wx.Panel(self,size=wx.DisplaySize())
    
            self.teamname=''
    
            ID_newgame=01
            ID_loadgame=02
            ID_overview=11
            ID_training=21
            ID_spiel=31
            ID_regeln=41
            ID_ueber=42
            #status=self.CreateStatusBar()
            menubar=wx.MenuBar()
            self.datei=wx.Menu()
            self.team=wx.Menu()
            self.training=wx.Menu()
            self.spiel=wx.Menu()
            self.info=wx.Menu()
            self.datei.Append(ID_newgame,"Neues Spiel")
            self.datei.Append(ID_loadgame,"Spiel laden...")
            self.team.Append(ID_overview,"Übersicht")
            self.training.Append(ID_training,"Trainieren")
            self.spiel.Append(ID_spiel,"Spielen")
            self.info.Append(ID_regeln,"Regeln")
            self.info.Append(ID_ueber,"Info")
            menubar.Append(self.datei,"Datei")
            menubar.Append(self.team,"Mannschaft")
            menubar.Append(self.training,"Training")
            menubar.Append(self.spiel,"Spiel")
            menubar.Append(self.info,"Info")
            self.SetMenuBar(menubar)
    
            self.titletext=wx.StaticText(self.startpanel, -1, self.title, (220,130))
            self.titletext.SetFont(titlefont)
            self.newgame = wx.Button(self.startpanel,label="Neues Spiel",pos=(215,160),size=(80,40))
            self.loadgame = wx.Button(self.startpanel,label="Spiel laden",pos=(305,160),size=(80,40))
    
            self.Bind(wx.EVT_BUTTON, self.dateinewgamepanelbuild, self.newgame)
            self.Bind(wx.EVT_BUTTON, self.dateiloadgamepanelbuild, self.loadgame)
    
            wx.EVT_MENU(self, ID_newgame, self.dateinewgamepanelbuild)
            wx.EVT_MENU(self, ID_loadgame, self.dateiloadgamepanelbuild)
            wx.EVT_MENU(self, ID_overview, self.teamoverviewpanelbuild)
            wx.EVT_MENU(self, ID_ueber, self.infopanelbuild)
    
    
        def hideallpanels(self):
            self.startpanel.Hide()
            self.dateinewgamepanel.Hide()
            self.dateiloadgamepanel.Hide()
            self.teamoverviewpanel.Hide()
            self.trainingpanel.Hide()
            self.spielpanel.Hide()
    
        def infopanelbuild(self,event):
            self.hideallpanels()
            self.infopanel.Show()
            wx.StaticText(self.infopanel,-1,"Autor: Steffen Becker")
    
        def dateinewgamepanelbuild(self,event):
            # panel neu zusammensetzen (mit aktuellen Werten), panel zeigen, alle anderen panels verstecken
            w=0
            h=-20
            self.hideallpanels()
            self.dateinewgamepanel.Show()
            #wx.StaticBitmap(self.dateinewgamepanel).SetBitmap(wx.Bitmap('pics/defaultplayer.bmp'))
            wx.StaticText(self.dateinewgamepanel, -1, "Neues Spiel", (5+w,25+h)).SetFont(wx.Font(16, wx.MODERN, wx.NORMAL, wx.BOLD))
            wx.StaticText(self.dateinewgamepanel, -1, "Teamname:", (self.displayw/4+10+w,self.displayh/10+20+h))
            self.teamnameinput = wx.TextCtrl(self.dateinewgamepanel, pos=(self.displayw/4+10+w,self.displayh/8+20+h), size=(280,22))
    
            wx.StaticText(self.dateinewgamepanel, -1, "Name 1. Spieler", (self.displayw/16+w,self.displayh/2+h))
            self.player1input = wx.TextCtrl(self.dateinewgamepanel, pos=(self.displayw/16+w,self.displayh/2+20+h), size=(130,20))
            wx.StaticText(self.dateinewgamepanel, -1, "Spielertyp", (self.displayw/16+w,self.displayh/2+60+h))
            self.player1typeinput = wx.Choice(self.dateinewgamepanel,id=-1,pos=(self.displayw/16+w,self.displayh/2+80+h))
            player1typelist = ['Dribbler', 'Spielgestalter', 'Balleroberer']
            self.player1typeinput.AppendItems(strings=player1typelist)
            self.player1typeinput.SetSelection(0)
            picplayer1=wx.Image("pics\defaultplayer.bmp", wx.BITMAP_TYPE_BMP).ConvertToBitmap()
            picbutplayer1=wx.BitmapButton(self.dateinewgamepanel,-1,picplayer1,pos=(self.displayw/16+w,self.displayh/2-140+h))
    
            wx.StaticText(self.dateinewgamepanel, -1, "Name 2. Spieler", (self.displayw*5/16+w,self.displayh/2+h))
            self.player2input = wx.TextCtrl(self.dateinewgamepanel, pos=(self.displayw*5/16+w,self.displayh/2+20+h), size=(130,20))
            wx.StaticText(self.dateinewgamepanel, -1, "Spielertyp", (self.displayw*5/16+w,self.displayh/2+60+h))
            self.player2typeinput = wx.Choice(self.dateinewgamepanel,id=-1,pos=(self.displayw*5/16+w,self.displayh/2+80+h))
            player2typelist = ['Dribbler', 'Spielgestalter', 'Balleroberer']
            self.player2typeinput.AppendItems(strings=player2typelist)
            self.player2typeinput.SetSelection(0)
            picplayer2=wx.Image("pics\defaultplayer.bmp", wx.BITMAP_TYPE_BMP).ConvertToBitmap()
            picbutplayer2=wx.BitmapButton(self.dateinewgamepanel,-1,picplayer2,pos=(self.displayw*5/16+w,self.displayh/2-140+h))
    
            wx.StaticText(self.dateinewgamepanel, -1, "Name 3. Spieler", (self.displayw*9/16+w,self.displayh/2+h))
            self.player3input = wx.TextCtrl(self.dateinewgamepanel, pos=(self.displayw*9/16+w,self.displayh/2+20+h), size=(130,20))
            wx.StaticText(self.dateinewgamepanel, -1, "Spielertyp", (self.displayw*9/16+w,self.displayh/2+60+h))
            self.player3typeinput = wx.Choice(self.dateinewgamepanel,id=-1,pos=(self.displayw*9/16+w,self.displayh/2+80+h))
            player3typelist = ['Dribbler', 'Spielgestalter', 'Balleroberer']
            self.player3typeinput.AppendItems(strings=player3typelist)
            self.player3typeinput.SetSelection(0)
            picplayer3=wx.Image("pics\defaultplayer.bmp", wx.BITMAP_TYPE_BMP).ConvertToBitmap()
            picbutplayer3=wx.BitmapButton(self.dateinewgamepanel,-1,picplayer3,pos=(self.displayw*9/16+w,self.displayh/2-140+h))
    
    
            #bmp = wx.Image('pics/defaultplayer.bmp', wx.BITMAP_TYPE_BMP).ConvertToBitmap()
            #wx.StaticBitmap(self.dateinewgamepanel, -1, bmp, (1100, 500))
    
            self.playerok = wx.Button(self.dateinewgamepanel,label="Team erstellen",pos=(self.displayw*5/16-20+w,self.displayh/2+170+h),size=(170,30))
            self.Bind(wx.EVT_BUTTON, self.onteamok, self.playerok)
            self.teamnameerror=wx.StaticText(self.dateinewgamepanel, -1, "Gib bitte überall einen Namen ein!", (self.displayw*5/16-15+w,self.displayh/2+210+h))
            self.teamnameerror.Hide()
    
        def dateiloadgamepanelbuild(self,event):
            self.hideallpanels()
            self.dateiloadgamepanel.Show()        
            wx.StaticText(self.dateiloadgamepanel, -1, "Noch nicht implementiert", (20,70))
    
        def teamoverviewpanelbuild(self,event):
            self.hideallpanels()
            self.teamoverviewpanel.Show()        
            wx.StaticText(self.teamoverviewpanel, -1, self.teamname, (120,10))
            wx.StaticText(self.teamoverviewpanel, -1, self.player1, (40,40))
            wx.StaticText(self.teamoverviewpanel, -1, self.player2, (120,40))
            wx.StaticText(self.teamoverviewpanel, -1, self.player3, (200,40))
    
    
        def onteamok(self,event):
            if self.teamnameinput.GetValue() == '' or self.player1input.GetValue() == '' or self.player2input.GetValue() == '' or self.player3input.GetValue() == '':
                self.teamnameerror.Show()
            else:
                self.teamname = self.teamnameinput.GetValue()
                self.player1 = self.player1input.GetValue()
                self.player2 = self.player2input.GetValue()
                self.player3 = self.player3input.GetValue()
                self.teamoverviewpanelbuild(event)
    
        def onloadgame(self,event):
            self.startpanel.Hide()
            self.dateinewgamepanel.Hide()
            self.dateiloadgamepanel.Show()
    
    
    
    
    
    if __name__=='__main__':
        app=wx.PySimpleApp()
        frame=myclass(parent=None,id=-1)
        frame.Show()
        app.MainLoop()
    


Answer: Here are my suggestions:

  * You're already familiar with deriving classes from `wx.Frame`. You can do the same for `wx.Panel` for the retrieving the player's data and parameterize it as you like. This would remove code duplication and make it more handy.
    
        class PlayerPanel(wx.Panel):
        def __init__(self, name, *args, **kwargs):
            wx.Panel.__init__(self, *args, **kwargs)
            wx.StaticText(self, -1, name)
            ..etc...
    

  * Derive another class from `wx.Frame` and separate the aspects of game creation and actual playing; get rid of hiding / showing panels.

  * Learn about layout management. When I want to get familiar with your code, the absolute calculation of the widget position is unacceptable to me. There are very nice examples on [Zetcode](http://zetcode.com/wxpython/).

  * Refactor all game logic into separate a seperate module. This module could contain the model and control classes of the MVC (model-view-controller) pattern. The view is written in wxPython, the game logic could be in a separate class and the model is e.g. another class for the player (name, age, ...).

  * Use a [`wx.MessageBox`](http://zetcode.com/wxpython/dialogs/) for error messages and the about dialog.

