0% found this document useful (0 votes)
65 views

Learning Python: Getting Results For Beamlines and Scientific Programming

The document discusses intermediate Python programming with the WxPython GUI toolkit. It provides an outline of topics to be covered, including a review of WxPython widgets and sizers, responding to events, the model-view-controller pattern, designing event handlers, validators, and multiple windows. Code examples are provided to demonstrate creating widgets and binding them to event handlers.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
65 views

Learning Python: Getting Results For Beamlines and Scientific Programming

The document discusses intermediate Python programming with the WxPython GUI toolkit. It provides an outline of topics to be covered, including a review of WxPython widgets and sizers, responding to events, the model-view-controller pattern, designing event handlers, validators, and multiple windows. Code examples are provided to demonstrate creating widgets and binding them to event handlers.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 28

Learning Python

Getting results for beamlines and scientific programming


Intermediate python: GUI programming with WxPython, part 3

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

Outline of topics to be covered

1.
2.
3.
4.
5.
6.

Quick wxPython (Sizers/Widgets/widget id) review


Responding to events
Model-View-Controller
Designing event handlers
Validators
MulBple windows (modal & non-modal)

Note that code used in examples in this talk are posted in a le oct19Examples.zip on
the Python Interest Group (PIG) web page.
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

REVIEW

OF WXPYTHON

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

Short wxPython sample application


Subclass wx.Frame
Call wx.Frame __init__
Create Panel as child of Frame (self)
Create sizer & associate with panel
Create widgets & add to sizer
Size window to match widgets
Set show ag on Frame

Create App
Create Frame
Start event loop

import wx!
class mywxframe(wx.Frame):!
def __init__(self):!
wx.Frame.__init__(self, None)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
w = wx.StaticText(!
pnl,wx.ID_ANY,'Widget #1')!
sizer.Add(w,0,wx.ALL,10)!
w = wx.StaticText(!
pnl,wx.ID_ANY,'... Widget #2')!
sizer.Add(w,0,wx.ALL,10)!
sizer.Fit(self)!
self.Show()!
!
app = wx.PySimpleApp() # create the App!
frm = mywxframe()!
wx4.py
app.MainLoop()!

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

We use Sizers to arrange widgets

wx.BoxSizer(wx.HORIZONTAL)

wx.BoxSizer(wx.VERTICAL)

Sizers can be placed in sizers for more complex


arrangements

10/19/11

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

Commonly used widgets


Making widgets tends to be easy
wx.Bu&on: creates a widget intended to
respond when clicked on by a mouse. Usually
labeled with text, but a variaBon, the
wx.BitmapBu&on, is labeled with a bitmap
image.
wx.CheckBox: creates a widget that can be
selected or unselected. An opBon is a 3-state
bucon that can be on, o or other.
wx.RadioBox where only one bucon in a group
can be selected.
wx.TextCtrl: creates a widget where a user can
enter text. May be single line or mulBline.
Probably the most widely used widget next to
bucons.
wx.Choice: oers a menu with a xed list of
opBons. (Also see wx.ComboBox.)

wx8.py

wx8a.py

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

Widget ids

Every widget in a window (frame) must have a unique id code. Usually this is done by
sehng the id parameter when a widget is created to be wx.ID_ANY (which is -1).
This is oien the default. If wx.ID_ANY is used, wxPython creates a unique id.

w = wx.StaticText(pnl,wx.ID_ANY,'Widget #1')

Most of the Bme one does not care about the id value. When you do need to know
the Id of a widget, it can be obtained using <widget>.GetID().

id = w.GetID()!

One excepBon, (to be shown later) there are some commonly used widgets, such as
Exit in menus, Yes & No bucons in dialogs, wx.Python denes standard Ids for these
and it is best to use them.
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

RESPONDING

TO EVENTS

Needed to wire up bucons, etc. to code

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

Binding an event to widgets


This is the preferred way to make a
binding. It it uses a method of the
widget (bucon) to connect to the
callback.

This rouBne referenced in the bind
will be called when the event
(wx.EVT_BUTTON) is generated
when a bucon is pressed.

class mywxframe(wx.Frame):!
def __init__(self):!
wx.Frame.__init__(self, None)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
btn = wx.Button(pnl, -1,!
"sample button")!
btn.Bind(wx.EVT_BUTTON, self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
!
sizer.Fit(self)!
self.Show()!
!
def OnClick(self, event):!
print 'Button pressed'!
wx9.py

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

Other commonly used events

wx.EVT_BUTTON
wx.EVT_CHECKBOX
wx.EVT_COMBOBOX
wx.EVT_SLIDER
wx.EVT_RADIOBOX!
wx.EVT_MENU!
wx.EVT_CLOSE
wx.EVT_SIZE!
wx.EVT_TEXT_ENTER
wx.EVT_KILL_FOCUS
wx.EVT_SET_FOCUS!
wx.EVT_KEY_UP
wx.EVT_MOUSEWHEEL!
wx.EVT_LEFT_DOWN
wx.EVT_MOTION!
!

!bucon press
!!
!

!called when the appropriate widget is operated!

!called when a frame (window) is closed/changed

!typing in a TextCtrl
! !generated when a widget is entered or lei
!when a keyboard key is released
!

!when a mouse bucon is pressed or the mouse is moved

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

10

Aside: The Model-View-Controller Design Paradigm

It is almost always a good idea to


write code in three separate secBons:
The model: which contains the
programs data structures and
domain logic
The view: which displays the
informaBon in the Model to the user
The controller: this allows the user to
interact and perhaps modify the
model
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

11

Model-View-Controller in Scientific Coding


The Model usually corresponds to the experimental data, hng parameters, and all the
computaBonal code used with that data.
The View will be the tables and graphics that are generated to allow the user to
visualize the contents of the Model
The Controller will be the GUI
These should all be in separate classes and, preferably, separate modules.

Why?
1. You may want to have an exclusively computaBonal program that operates for long
periods or runs on a cluster. This will need to use the Model without any code from the
View or Controller
2. You may want to replace or augment the visualizaBon, and do not want to have to
replace all code
3. You may decide to create dierent types of GUIs and again want to reuse as much code
as possible.
Note that this is only a paradigm. For scienFc soGware, someFmes it makes sense to
combine the view and controller, or more rarely, the model and view, but always keep the
GUI separate from the computaFon/data storage module(s).
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

12

Getting information into an event handler

One of the problems in event-driven programming is that events live in the


Controller layer, but aect parameters in the Model and/or operaBon of the View.
Even though when will have access to the Model and View objects when the code
to build the GUI and setup the bind is execuBng, there is no way to pass this into
the event handler.
One choice is to place the event handler in the Model or View objects, but this has
problems since this is oien GUI-specic code that really should live in the
Controller.

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

13

import wx!
class mycalc:!
def __init__(self):!
self.myvar = None!
def SetVar(self,val):!
self.myvar = val!
!
class myframe(wx.Frame):!
This code has two classes:
def __init__(self):!
wx.Frame.__init__(self, None)!
mycalc (for data/computaBon) &
pnl = wx.Panel(self)!
myframe (GUI implementaBon)
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
we really want them separate
btn = wx.Button(pnl, -1,"read")!

btn.Bind(wx.EVT_BUTTON, self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
My hokey GUI example: pressing
self.tc = wx.TextCtrl(pnl, -1,!
bucon reads TextCtrl and then
'xxx',size=(100,-1))!
disables it so it cant be changed.
sizer.Add(self.tc,0,wx.ALL,10)
!
sizer.Fit(self)!

self.Show()!
!
The GUI part of this is implemented
def OnClick(self, event):!
here, but I need to get the value I
print 'Value = ',self.tc.GetValue()!
read into the mycalc object.
# but how do I get value into CalcObj?!
self.tc.Disable() # disable the TextCtrl!
How can I do this?
!
app = wx.PySimpleApp() # create the App!
CalcObj = mycalc()!
frm =of Energy
myframe()!
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department
Oce of Science by Argonne NaBonal Laboratory
app.MainLoop()!
14
wx10.py

Example of the
information routing
problem

10/19/11

Solution: save pointers


to required objects
Note that the only way to get
informaBon into the event handler is
by dening variables in the class for
later use. This is usually done in the
__init__ funcBon for the class.

When I create frm (class myframe), I
pass it a reference to the data object
(CalcObj, class mycalc).

This gets saved in the myframe class

The OnClick method can then access
the data object

!
class myframe(wx.Frame):!
def __init__(self,DataObj):!
wx.Frame.__init__(self, None)!
self.DataObj = DataObj!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
btn = wx.Button(pnl, -1,"read")!
btn.Bind(wx.EVT_BUTTON, self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
self.tc = wx.TextCtrl(pnl, -1,!
'xxx',size=(100,-1))!
sizer.Add(self.tc,0,wx.ALL,10)
!
sizer.Fit(self)!
self.Show()!
!
def OnClick(self, event):!
# here I put the value into CalcObj:!
self.DataObj.SetVar(self.tc.GetValue())!
self.tc.Disable() # disable the TextCtrl!
!
app = wx.PySimpleApp() # create the App!
CalcObj = mycalc()!
frm = myframe(CalcObj)!
app.MainLoop()!
print 'saved val = ',CalcObj.myvar!

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

wx10a.py
15

Implementing a generic event handler

Save info in dict(s) indexed by widget Id or by widget object that will be used to
determine what the event handler will do
If the event handler will need to do dierent things based on what type of event
occurred, also look up the event type Id
(for example tId = wx.EVT_BUTTON.typeId).
Use a nested dict?
In the event handler use event parameter to get informaBon on the widget causing
the event and the event type:
event.GetId(): provides the Id of the widget that generated the event
event.GetEventObject(): provides the object that generated the event
event.GetEventType(): provides the event type Id

To see what else is available, use print(dir(event)). Note that dierent


types of events have dierent methods and values dened,
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

16

Generic Event Handler Example


class mywxframe(wx.Frame):!
def __init__(self,DataObj):!
wx.Frame.__init__(self, None)!
self.DataObj = DataObj!
self.DisableList = {}!
self.SetList = {}!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
btn = wx.Button(pnl, -1,"read")!
btn.Bind(wx.EVT_BUTTON, self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
self.tc = wx.TextCtrl(pnl, -1,!
'xxx',size=(100,-1))!
id = btn.GetId()!
print 'Button id =',id!
self.DisableList[id] = self.tc!
self.SetList[id] = self.DataObj.SetVar!
!
sizer.Add(self.tc,0,wx.ALL,10)
!
sizer.Fit(self)!
self.Show()!
wx10b.py

def OnClick(self, event):!


id = event.GetId() !
print 'Button pressed is =',id!
sl = self.SetList.get(id)!
if sl is not None: !
sl(self.tc.GetValue())!
disabl = self.DisableList.get(id)!
if disabl is not None:!
disabl.Disable() # disable!

bht3:tutorial toby$ python wx10b.py


Bucon id = -203
Bucon pressed is = -203
saved val = yyy

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

17

Another variant, use object as a key rather than id


class mywxframe(wx.Frame):!
def __init__(self,DataObj):!
wx.Frame.__init__(self, None)!
self.DataObj = DataObj!
self.DisableList = {}!
self.SetList = {}!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
btn = wx.Button(pnl, -1,"read")!
btn.Bind(wx.EVT_BUTTON, self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
self.tc = wx.TextCtrl(pnl, -1,!
'xxx',size=(100,-1))!
print 'Button =',btn!
self.DisableList[btn] = self.tc!
self.SetList[btn] = self.DataObj.SetVar!
!
sizer.Add(self.tc,0,wx.ALL,10)
!
sizer.Fit(self)!
self.Show()!
wx10c.py

def OnClick(self, event):!


btn = event.GetEventObject()!
print 'EventObject =',btn!
sl = self.SetList.get(btn)!
if sl is not None: !
sl(self.tc.GetValue())!
dis = self.DisableList.get(btn)!
if dis is not None:!
dis.Disable() # disable!

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

18

Validators
Validators are classes that can be associated with TextCtrl widgets. The validator can
check each character as it is typed into the box (and possibly ignore invalid characters)
or it can check if the contents is valid.

I have a pair of sample validators on the PIG web page (le validators.py:
hcps://conuence.aps.anl.gov/download/acachments/2523138/validators.py)
One enforces that the values entered match that of a unsigned or opBonally
signed integer. Any other character is ignored.
When the box loses focus, the enBre contents is checked to make sure it is a valid
integer. If not, the widget is highlighted
OpBonally a funcBon can be supplied to execute on a valid integer
Minimum and maximum values can be specied

The other is for oats, opBonally with exponenBal notaBon (e or E is allowed)


When the box loses focus, the enBre contents is checked to make sure it is a valid oat.
If not, the widget is highlighted
OpBonally a funcBon can be supplied to execute on a valid oat

The validator is used very simply, by adding a parameter to the TextCtrl


The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

19

Validator example
import wx!
import validators!
class mycalc:!
def __init__(self):!
self.myvar = None!
def SetVar(self,val,obj):!
self.myvar = val!

app = wx.PySimpleApp() # create App!


CalcObj = mycalc()!
frm = mywxframe(CalcObj)!
app.MainLoop()!
print 'saved val = ',CalcObj.myvar!

class mywxframe(wx.Frame):!
def __init__(self,DataObj):!
wx.Frame.__init__(self, None)!
self.DataObj = DataObj!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
!
w = wx.StaticText(pnl, -1,!
"Only integers here")!
sizer.Add(w,0,wx.ALL,10)!
tc = wx.TextCtrl(!
pnl, -1, size=(100,-1),!
validator=validators.IntValidator(!
positiveonly=False))!
sizer.Add(tc,0,wx.ALL,5)!
!
w = wx.StaticText(pnl, -1,"Floats here")!
sizer.Add(w,0,wx.ALL,10)!
tc = wx.TextCtrl(!
pnl, -1,size=(100,-1),!
validator=validators.FloatValidator(!
DataObj.SetVar))!
sizer.Add(tc,0,wx.ALL,5)!
!
sizer.Fit(self)!
self.Show()!
wx11.py

hcps://conuence.aps.anl.gov/download/
acachments/2523138/validators.py)
10/19/11

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

20

Modal dialogs

Modal dialogs are used to display informaBon to the user (such as an error message)
or get input from the user via a new window; the program does not allow anything
else to occur unBl the user has closed the new window.

The easiest way to implement a modal dialog is to use one of the many stock
widgets in wxPython, such as DirDialog, FIleDialog, MessageDialog,
TextEntryDialog (~15 choices in total)

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

21

MessageDialog Example
class mywxframe(wx.Frame):!
def __init__(self):!
wx.Frame.__init__(self, None)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
btn = wx.Button(pnl, -1,!
"Show message")!
btn.Bind(wx.EVT_BUTTON,!
self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
self.Show()!
!
def OnClick(self, event):!
dlg = wx.MessageDialog(self,!
"Prompt:\n\tYou rang?",!
'Title: Waddayawant?',!
wx.OK | wx.CANCEL |!
wx.ICON_QUESTION)!
if dlg.ShowModal() == wx.ID_OK:!
print "OK!"!
dlg.Destroy()!
wx12.py

The dialog is created in response to


the bucon. The main window is
inacBve when the dialog is open.

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

22

FileDialog Example
class mywxframe(wx.Frame):!
def __init__(self):!
wx.Frame.__init__(self, None)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
btn = wx.Button(pnl, -1,!
"Get file")!
btn.Bind(wx.EVT_BUTTON, self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
sizer.Fit(self)!
self.Show()!
!
def OnClick(self, event):!
wildcard = "pickle files (*.pkl)|*.pkl"!
dlg = wx.FileDialog(!
self, message="Save as...", !
defaultDir="/tmp", !
defaultFile="test.pkl",!
wildcard=wildcard,!
#style=wx.FD_OPEN!
style=wx.FD_SAVE)!
if dlg.ShowModal() == wx.ID_OK:!
print 'path = ',dlg.GetPath()!
else:!
print 'Cancelled!'!
wx12a.py

The dialog is created in response to


the bucon. The main window is
inacBve when the dialog is open.
The dialog uses the naBve le
browser for the OS/WM of
computer

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

23

For complex modal dialogs, subclass wx.Dialog


class TestDialog(wx.Dialog):!
def __init__(self, parent, ID):!
# Instead of calling wx.Dialog.__init__ we use this:!
pre = wx.PreDialog()!
pre.Create(parent, ID, "Override the defaults, wx.DefaultPosition,!
wx.DefaultSize, wx.DEFAULT_DIALOG_STYLE)!
self.PostCreate(pre)!
sizer = wx.BoxSizer(wx.VERTICAL)!
label = wx.StaticText(self, -1, "Variables used in data collection")!
sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)!
line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL)!
sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, 5)!
label = wx.StaticText(self, -1, "(useful stuff goes here)")!
sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)!
btnsizer = wx.StdDialogButtonSizer()!
btn = wx.Button(self, wx.ID_OK)!
btn.SetDefault()!
btnsizer.AddButton(btn)!
btn = wx.Button(self, wx.ID_CANCEL)!
btnsizer.AddButton(btn)!
btnsizer.Realize()!
sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)!
self.SetSizer(sizer)!
sizer.Fit(self)!
pre.CenterOnParent()!
wx14.py
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

24

Using the subclassed wx.Dialog (pretty much like


any other Dialog)
import wx!
class mywxframe(wx.Frame):!
def
__init__(self):!
te
wx.Frame.__init__(self, None)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
btn = wx.Button(pnl, -1,!
"Get stuff")!
btn.Bind(wx.EVT_BUTTON, self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
sizer.Fit(self)!
self.Show()!
!
def OnClick(self, event):!
dlg = TestDialog(self, -1)!
# returns after window is closed!
val = dlg.ShowModal()!
if val != wx.ID_OK: !
dlg.Destroy() # cancel was pressed!
return!
# do something with dlg contents here!
dlg.Destroy() # close it!
return!
wx14.py

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

25

Non-modal windows
import wx!
class mywxframe(wx.Frame):!
def __init__(self,parent,lbl):!
wx.Frame.__init__(self, parent)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
w = wx.StaticText(pnl, -1, lbl)!
sizer.Add(w,0,wx.ALL,10)!
sizer.Fit(self)!
self.Show()!
!
app = wx.PySimpleApp() # create the App!
frm1 = mywxframe(None, '1st window')!
frm2 = mywxframe(None, '2nd window')!
frm3 = mywxframe(None, '3rd window')!
app.MainLoop()!
print 'event loop done'!
wx13.py

Frames can be top level with


no parents. Each window has no
parent and thus is independent.
The Event loop runs unBl all
are closed

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

26

Child windows

Here each new frame is a child of the


former. Only the rst is top level (no
parent).
Closing the 2nd window kills the 3rd.
Closing the 1st window kills all
The Event loop runs unBl all are
closed which is now Bed to the 1st
window.

import wx!
class mywxframe(wx.Frame):!
def __init__(self,parent,lbl):!
wx.Frame.__init__(self, parent)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
w = wx.StaticText(pnl, -1, lbl)!
sizer.Add(w,0,wx.ALL,10)!
sizer.Fit(self)!
self.Show()!
!
app = wx.PySimpleApp() # create the App!
frm1 = mywxframe(None, '1st window')!
frm2 = mywxframe(frm1, '2nd window\nchild of 1st')!
frm3 = mywxframe(frm2, '3rd window\nchild of 2nd')!
app.MainLoop()!
print 'event loop done!
wx13a.py

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

27

Homework

Create a small wxPython program to do something useful. Let me know what you
did or where you get stuck.

The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory

10/19/11

28

You might also like