Creating a Collection of Controls

This recipe shows how to create an aligned column of buttons on a panel by creating the buttons as instances of a nested class.

   1 from   wxPython.wx     import *
   2 
   3 class ButtonColumn ( wxPanel ):
   4     '''Create aligned column of equal-sized buttons with distinct labels and OnClick destinations.
   5 
   6     Illustrates use of nested classes for creating a collection of controls.
   7     '''
   8     class aButton ( wxButton ):
   9         '''Nested button class for use by ButtonColumn class.'''
  10         def __init__ ( self, parent, label, whotocall ):
  11             """Expects reference to 'ButtonColumn', list of labels for buttons and list of functions to be called for OnClick events"""
  12             id = wxNewId ( )
  13             wxButton.__init__ ( self, parent, id, label, wxDefaultPosition, wxDefaultSize, 1 )
  14             self.whotocall = whotocall
  15             EVT_BUTTON ( self, id, self.OnClick )
  16 
  17         def OnClick ( self, event ):
  18             if self.whotocall: self.whotocall ( )
  19 
  20     def __init__ ( self, parent, width, buttons, Bottom = 0 ):
  21         """Expects reference to 'parent' of 'ButtonColumn', button column 'width', list of button descriptor tuples, and number of buttons to be displayed at the bottom of the column.
  22 
  23         Each button descriptor consists of a label for the button and a reference to the function to be called when the button is clicked.
  24         """
  25         wxPanel.__init__ ( self, parent, -1, wxDefaultPosition, ( 100, 200 ) )
  26         self.parent = parent
  27 
  28         """Create the upper collection of buttons"""
  29         previous = None
  30         for button in buttons [ 0 : len ( buttons ) -Bottom ]:
  31             oneButton = self.aButton ( self, button [ 0 ], button [ 1 ] )
  32             lc = wxLayoutConstraints ( )
  33             lc.left.SameAs ( self, wxLeft, 5 )
  34             lc.right.SameAs ( self, wxRight, 5 )
  35             lc.height.AsIs ( )
  36             if previous: lc.top.SameAs ( previous, wxBottom, 5 )
  37             else: lc.top.SameAs ( self, wxTop, 5 )
  38             oneButton.SetConstraints ( lc )
  39             previous = oneButton
  40 
  41         """Create the lower collection of buttons"""
  42         buttons.reverse ( )
  43         previous = None
  44         for button in buttons [ 0 : Bottom ]:
  45             oneButton = self.aButton ( self, button [ 0 ], button [ 1 ] )
  46             lc = wxLayoutConstraints ( )
  47             lc.left.SameAs ( self, wxLeft, 5 )
  48             lc.right.SameAs ( self, wxRight, 5 )
  49             lc.height.AsIs ( )
  50             if previous: lc.bottom.SameAs ( previous, wxTop, 5 )
  51             else: lc.bottom.SameAs ( self, wxBottom, 5 )
  52             oneButton.SetConstraints ( lc )
  53             previous = oneButton
  54 
  55 if __name__ == '__main__':
  56     class TestFrame(wxFrame):
  57         def __init__(self):
  58             wxFrame.__init__ (
  59                 self, None, -1, "Button Column Test",
  60                 size = ( 450, 300 ),
  61                 style = wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE
  62                 )
  63             self.SetAutoLayout ( true )
  64             buttons = [
  65                 ( 'OK', self.OKClicked, ),
  66                 ( 'Cancel', self.CancelClicked, ),
  67                 ( 'Re-invert', self.ReinvertClicked, ),
  68                 ( 'Exit', self.ExitClicked, ),
  69                 ]
  70 
  71             self.tp = ButtonColumn ( self, 45, buttons, 2 )
  72 
  73             lc = wxLayoutConstraints ( )
  74             lc.right.SameAs ( self, wxRight)
  75             lc.width.AsIs ( )
  76             lc.top.SameAs ( self, wxTop )
  77             lc.bottom.SameAs ( self, wxBottom )
  78             self.tp.SetConstraints ( lc )
  79 
  80             self.CreateStatusBar ( )
  81 
  82         def OKClicked ( self ):
  83             print "OKClicked"
  84 
  85         def CancelClicked ( self ):
  86             print "CancelClicked"
  87 
  88         def ReinvertClicked ( self ):
  89             print "ReInvertClicked"
  90 
  91         def ExitClicked ( self ):
  92             self.Close ( )
  93 
  94     app = wxPySimpleApp()
  95     frame = TestFrame()
  96     frame.Show(true)
  97     app.MainLoop()

Comments to Bill Bell

Another Way

This is a Scheme-ish method of making collections of controls. It's nice because it's easy to rearrange structure:

   1 spec =[hbox,
   2        [spacer, 350,200, 0],
   3        [vbox,
   4         [button, "OK",        self.OKClicked],
   5         [button, "Cancel",    self.CancelClicked],
   6         [spacer,  10,100, 1],
   7         [button, "Re-invert", self.ReinvertClicked],
   8         [button, "Exit",      self.ExitClicked]]]

Full code follows. I suspect it can be made even tighter.

   1 from   wxPython.wx     import *
   2 
   3 def new_sizer( form, lst, sizer, orientation ):
   4     "Called by *vbox* and *hbox* with orientation:(wxVERTICAL or wxHORIZONTAL)"
   5     new_sizer = wxBoxSizer( orientation )
   6     for item in lst[1:]:
   7         item[0]( form, item, new_sizer )
   8     sizer.Add( new_sizer, 1, wxGROW )
   9 def vbox( form, lst, sizer ):
  10     new_sizer( form, lst, sizer, wxVERTICAL )
  11 def hbox( form, lst, sizer ):
  12     new_sizer( form, lst, sizer, wxHORIZONTAL )
  13 def spacer( form, lst, sizer ):
  14     "grows can be 1 or 0"
  15     (cmd, wide,high, grows)=lst
  16 
  17     sizer.Add( wide,high, grows )
  18 
  19 def button( form, lst, sizer ):
  20     (cmd, label,method)=lst
  21 
  22     id=wxNewId()
  23     sizer.Add( wxButton( form, id, label, style=wxBU_EXACTFIT ), 0, wxGROW )
  24     EVT_BUTTON( form, id, method )
  25 
  26 
  27 class TestFrame(wxFrame):
  28     def __init__(self):
  29         wxFrame.__init__(
  30             self, None, -1, "Button Column Test",
  31             size = ( 450, 300 ),
  32             style = wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE )
  33 
  34         spec=[hbox,
  35               [spacer, 350,200, 0],
  36               [vbox,
  37                [button, "OK",        self.OKClicked],
  38                [button, "Cancel",    self.CancelClicked],
  39                [spacer,  10,100, 1],
  40                [button, "Re-invert", self.ReinvertClicked],
  41                [button, "Exit",      self.ExitClicked]]]
  42 
  43         master_sizer=wxBoxSizer( wxVERTICAL )
  44         spec[0]( self, spec, master_sizer ) # build from spec
  45         self.SetSizer( master_sizer )
  46         self.SetAutoLayout( 1 )
  47 
  48         self.CreateStatusBar ( )
  49 
  50     def OKClicked ( self, evt ):
  51         print "OKClicked"
  52     def CancelClicked ( self, evt ):
  53         print "CancelClicked"
  54     def ReinvertClicked ( self, evt ):
  55         print "ReInvertClicked"
  56     def ExitClicked ( self, evt ):
  57         self.Close()
  58 
  59 app = wxPySimpleApp()
  60 frame = TestFrame()
  61 frame.Show(1)
  62 app.MainLoop()

CreatingCollectionOfControls (last edited 2008-03-11 10:50:35 by localhost)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.