Skip to content

Commit 2316278

Browse files
added a bit about code-generated GUIs
1 parent e895014 commit 2316278

3 files changed

Lines changed: 194 additions & 4 deletions

File tree

week-09/code/CalculatorDemo.py

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#!/usr/bin/env python
2+
3+
"""
4+
wxPython Calculator Demo in 50 lines of code
5+
6+
This demo was pulled from the wxPython Wiki:
7+
8+
http://wiki.wxpython.org/CalculatorDemo
9+
by Miki Tebeka
10+
11+
It has been altered to allow it to be "driven" by an external script,
12+
plus a little layout improvement
13+
14+
See CalcualtorDemoDriver.py
15+
16+
for an example
17+
"""
18+
19+
20+
# Calculator GUI:
21+
22+
# ___________v
23+
# [7][8][9][/]
24+
# [4][5][6][*]
25+
# [1][2][3][-]
26+
# [0][.][C][+]
27+
# [ = ]
28+
29+
from __future__ import division # So that 8/3 will be 2.6666 and not 2
30+
import wx
31+
from math import * # So we can evaluate "sqrt(8)"
32+
33+
34+
class Calculator(wx.Panel):
35+
'''Main calculator dialog'''
36+
def __init__(self, *args, **kwargs):
37+
wx.Panel.__init__(self, *args, **kwargs)
38+
sizer = wx.BoxSizer(wx.VERTICAL) # Main vertical sizer
39+
40+
self.display = wx.ComboBox(self, -1) # Current calculation
41+
sizer.Add(self.display, 0, wx.EXPAND|wx.BOTTOM, 8) # Add to main sizer
42+
43+
# [7][8][9][/]
44+
# [4][5][6][*]
45+
# [1][2][3][-]
46+
# [0][.][C][+]
47+
gsizer = wx.GridSizer(4, 4, 8, 8)
48+
for row in (("7", "8", "9", "/"),
49+
("4", "5", "6", "*"),
50+
("1", "2", "3", "-"),
51+
("0", ".", "C", "+")):
52+
for label in row:
53+
b = wx.Button(self, label=label, size=(40,-1))
54+
gsizer.Add(b)
55+
b.Bind(wx.EVT_BUTTON, self.OnButton)
56+
sizer.Add(gsizer, 1, wx.EXPAND)
57+
58+
# [ = ]
59+
b = wx.Button(self, label="=")
60+
b.Bind(wx.EVT_BUTTON, self.OnButton)
61+
sizer.Add(b, 0, wx.EXPAND|wx.ALL, 8)
62+
self.equal = b
63+
64+
# Set sizer and center
65+
self.SetSizerAndFit(sizer)
66+
67+
def OnButton(self, evt):
68+
'''Handle button click event'''
69+
70+
# Get title of clicked button
71+
label = evt.GetEventObject().GetLabel()
72+
73+
if label == "=": # Calculate
74+
self.Calculate()
75+
elif label == "C": # Clear
76+
self.display.SetValue("")
77+
78+
else: # Just add button text to current calculation
79+
self.display.SetValue(self.display.GetValue() + label)
80+
self.display.SetInsertionPointEnd()
81+
self.equal.SetFocus() # Set the [=] button in focus
82+
83+
def Calculate(self):
84+
"""
85+
do the calculation itself
86+
87+
in a separate method, so it can be called outside of a button event handler
88+
"""
89+
try:
90+
compute = self.display.GetValue()
91+
# Ignore empty calculation
92+
if not compute.strip():
93+
return
94+
95+
# Calculate result
96+
result = eval(compute)
97+
98+
# Add to history
99+
self.display.Insert(compute, 0)
100+
101+
# Show result
102+
self.display.SetValue(str(result))
103+
except Exception, e:
104+
wx.LogError(str(e))
105+
return
106+
107+
def ComputeExpression(self, expression):
108+
"""
109+
Compute the expression passed in.
110+
111+
This can be called from another class, module, etc.
112+
"""
113+
print "ComputeExpression called with:", expression
114+
self.display.SetValue(expression)
115+
self.Calculate()
116+
117+
class MainFrame(wx.Frame):
118+
def __init__(self, *args, **kwargs):
119+
kwargs.setdefault('title', "Calculator")
120+
wx.Frame.__init__(self, *args, **kwargs)
121+
122+
self.calcPanel = Calculator(self)
123+
124+
# put the panel on -- in a sizer to give it some space
125+
S = wx.BoxSizer(wx.VERTICAL)
126+
S.Add(self.calcPanel, 1, wx.GROW|wx.ALL, 10)
127+
self.SetSizerAndFit(S)
128+
self.CenterOnScreen()
129+
130+
131+
if __name__ == "__main__":
132+
# Run the application
133+
app = wx.App(False)
134+
frame = MainFrame(None)
135+
frame.Show()
136+
app.MainLoop()
137+

week-09/presentation-week09.pdf

4.98 KB
Binary file not shown.

week-09/presentation-week09.tex

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ \section{Introduction}
5050
{\large Traditional Graphical User Interface Applications}
5151

5252
\vfill
53-
{\large Run entirely on machine -- interative, interface and logic code in one process}
53+
{\large Run entirely on machine -- interactive, interface and logic code in one process}
5454

5555
\vfill
5656

@@ -862,6 +862,62 @@ \section{controls}
862862
\end{frame}
863863

864864

865+
%---------------------------------
866+
\begin{frame}[fragile]{Code-generated GUIs...}
867+
868+
\vfill
869+
{\large You shouldn't write the same repetitive code for a GUI..}
870+
871+
\vfill
872+
{\large Or even need to build a GUI to match data at run time.}
873+
874+
\vfill
875+
{\large Lots of ways to do that with wxPython -- Sizers help a lot.}
876+
877+
\vfill
878+
{\large Try to do it whenever you find yourself writing repetitive code...}
879+
880+
\vfill
881+
{\large The key is how to do the event Binding}
882+
\begin{verbatim}
883+
def OnButton(self, evt):
884+
label = evt.GetEventObject().GetLabel()
885+
886+
do_somethign_with_label(label)
887+
\end{verbatim}
888+
\vfill
889+
example: \verb`code/CalculatorDemo.py`
890+
\end{frame}
891+
892+
%---------------------------------
893+
\begin{frame}[fragile]{Code-generated GUIs...}
894+
895+
\vfill
896+
{\Large The ``lambda trick''}
897+
898+
\vfill
899+
{\large -- a way to pass custom data to an event handler:}
900+
901+
\vfill
902+
{\large The key is how to do the event Binding}
903+
\begin{verbatim}
904+
for name in ["first", "second", "third"]:
905+
btn = wx.Button(self, label=name)
906+
btn.Bind(wx.EVT_BUTTON,
907+
lambda evt, n=name: self.OnButton(evt, n) )
908+
....
909+
def OnButton(self, Event, name):
910+
print "In OnButton:", name
911+
912+
\end{verbatim}
913+
914+
\vfill
915+
\url{http://wiki.wxpython.org/Passing%20Arguments%20to%20Callbacks}
916+
\end{frame}
917+
918+
919+
\section{Miscellaneous}
920+
865921
%-------------------------------
866922
\begin{frame}[fragile]{Long Running Tasks}
867923

@@ -886,7 +942,6 @@ \section{controls}
886942

887943
\end{frame}
888944

889-
\section{Miscellaneous}
890945

891946
%-------------------------------
892947
\begin{frame}[fragile]{CallAfter}
@@ -912,8 +967,6 @@ \section{Miscellaneous}
912967
\end{frame}
913968

914969

915-
916-
917970
%-------------------------------
918971
\begin{frame}[fragile]{BILS}
919972

0 commit comments

Comments
 (0)