Designing a Calculator in wxPython - Creating the Layout
(Page 3 of 4 )
Let's start with a frame and make our way forward. Go ahead and put down the basics:
from wxPython.wx import *
class CalculatorFrame ( wxFrame ):
def __init__ ( self ):
wxFrame.__init__ ( self, None, -1, 'PyCalc' )
self.Show ( True )
calculator = wxPySimpleApp()
CalculatorFrame()
calculator.MainLoop()
Now we'll add the wxGridBagSizer and the display. Borders of 1 and 1 look good with our calculator, though you can pick whatever reasonable (or unreasonable) value you want:
from wxPython.wx import *
class CalculatorFrame ( wxFrame ):
def __init__ ( self ):
wxFrame.__init__ ( self, None, -1, 'PyCalc' )
# Create a panel
self.panel = wxPanel ( self, -1 )
# Create a wxGridBagSizer
self.sizer = wxGridBagSizer ( 1, 1 )
# Add a display that takes up the whole row
self.display = wxTextCtrl ( self.panel, -1, '0.', style = wxTE_READONLY | wxTE_RIGHT )
self.sizer.Add ( self.display, ( 0, 0 ), ( 1, 5 ), wxEXPAND )
# Attach the sizer and adjust the frame size
self.panel.SetSizerAndFit ( self.sizer )
self.SetClientSize ( self.panel.GetSize() )
self.Show ( True )
calculator = wxPySimpleApp()
CalculatorFrame()
calculator.MainLoop()
If you execute our calculator, it looks horrid, but I promise you that things will improve once we're finished. Next come the buttons. Instead of calling wxGridBagSizer's Add method over a dozen times, we'll create a list for our buttons. The list will contain one list for each row. These lists will contain one list for each button, which will contain the button's text and the button's ID number. For spaces we do not want to occupy with buttons, we will put in None. This may sound complicated in a paragraph, but it makes a lot more sense when we put it in Python. We will then add everything to the grid with a loop:
from wxPython.wx import *
class CalculatorFrame ( wxFrame ):
def __init__ ( self ):
wxFrame.__init__ ( self, None, -1, 'PyCalc' )
self.panel = wxPanel ( self, -1 )
self.sizer = wxGridBagSizer ( 1, 1 )
self.display = wxTextCtrl ( self.panel, -1, '0.', style = wxTE_READONLY | wxTE_RIGHT )
self.sizer.Add ( self.display, ( 0, 0 ), ( 1, 5 ), wxEXPAND )
# Create the list of lists of lists of buttons
buttons = [ [ None, None, None, None, None ], \
[ [ 'M+', 100 ], [ '1', 1 ], [ '2', 2 ], [ '3', 3 ], [ '+', 200 ] ], \
[ [ 'M-', 101 ], [ '4', 4 ], [ '5', 5 ], [ '6', 6 ], [ '-', 201 ] ], \
[ [ 'MR', 102 ], [ '7', 7 ], [ '8', 8 ], [ '9', 9 ], [ '*', 202 ] ], \
[ None, [ '.', 103 ], [ '0', 0 ], [ '=', 104 ], [ '/', 203 ] ], \
[ None, None, [ 'B', 105 ], [ '+/-', 106 ], [ 'sqrt', 204 ] ] ]
# Add the buttons
x = y = 0
for row in buttons:
for button in row:
if button == None:
x = x + 1
continue
self.sizer.Add ( wxButton ( self.panel, button [ 1 ], button [ 0 ], size = ( 30, 30 ) ), ( y, x ) )
x = x + 1
x = 0
y = y + 1
self.panel.SetSizerAndFit ( self.sizer )
self.SetClientSize ( self.panel.GetSize() )
self.Show ( True )
calculator = wxPySimpleApp()
CalculatorFrame()
calculator.MainLoop()
Finally, we'll add our memory display and our two-column clear button:
from wxPython.wx import *
class CalculatorFrame ( wxFrame ):
def __init__ ( self ):
wxFrame.__init__ ( self, None, -1, 'PyCalc' )
self.panel = wxPanel ( self, -1 )
self.sizer = wxGridBagSizer ( 1, 1 )
self.display = wxTextCtrl ( self.panel, -1, '0.', style = wxTE_READONLY | wxTE_RIGHT )
self.sizer.Add ( self.display, ( 0, 0 ), ( 1, 5 ), wxEXPAND )
# Add the memory display and center everything
self.memoryDisplay = wxStaticText ( self.panel, -1, '0', style = wxALIGN_CENTER )
self.sizer.Add ( self.memoryDisplay, ( 4, 0 ), ( 1, 1 ), wxALIGN_CENTER )
# Add the two-column clear button
self.sizer.Add ( wxButton ( self.panel, 107, 'Clear', size = ( 30, 30 ) ), ( 5, 0 ), ( 1, 2 ), wxEXPAND )
buttons = [ [ None, None, None, None, None ], \
[ [ 'M+', 100 ], [ '1', 1 ], [ '2', 2 ], [ '3', 3 ], [ '+', 200 ] ], \
[ [ 'M-', 101 ], [ '4', 4 ], [ '5', 5 ], [ '6', 6 ], [ '-', 201 ] ], \
[ [ 'MR', 102 ], [ '7', 7 ], [ '8', 8 ], [ '9', 9 ], [ '*', 202 ] ], \
[ None, [ '.', 103 ], [ '0', 0 ], [ '=', 104 ], [ '/', 203 ] ], \
[ None, None, [ 'B', 105 ], [ '+/-', 106 ], [ 'sqrt', 204 ] ] ]
x = y = 0
for row in buttons:
for button in row:
if button == None:
x = x + 1
continue
self.sizer.Add ( wxButton ( self.panel, button [ 1 ], button [ 0 ], size = ( 30, 30 ) ), ( y, x ) )
x = x + 1
x = 0
y = y + 1
self.panel.SetSizerAndFit ( self.sizer )
self.SetClientSize ( self.panel.GetSize() )
self.Show ( True )
calculator = wxPySimpleApp()
CalculatorFrame()
calculator.MainLoop()
Our layout is now finished. If you wish, you can adjust the sizes and borders to fit your tastes.
Next: Wiring It All Together >>
More Python Articles
More By Peyton McCullough