Differences between revisions 50 and 58 (spanning 8 versions)
Revision 50 as of 2008-07-29 11:38:11
Size: 5225
Editor: cpc3-warw6-0-0-cust905
Comment:
Revision 58 as of 2012-06-28 08:10:48
Size: 10371
Editor: SWM-HIGH-SPEED2-22
Comment: Made code use python highlight
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
'''Contents'''
<<TableOfContents(2)>>

== A Full Example ==
Line 6: Line 11:
#!python
Line 51: Line 57:
        self.Bind(wx.EVT_CLOSE, self.OnClose)
Line 80: Line 88:
        self.Close()         dlg = wx.MessageDialog(self,
            "Do you really want to close this application?",
            "Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
        result = dlg.ShowModal()
        dlg.Destroy()
        if result == wx.ID_OK:
            self.Destroy()
Line 90: Line 104:
app.SetTopWindow(top)
app.MainLoop()
}}}
app.MainLoop()
}}}

== A Bare-Bones Application ==
Line 97: Line 112:
#!python
Line 102: Line 118:
app.SetTopWindow(top)
app.MainLoop()
}}}

 * The first thing to do in the main program is to create the wx.App object that provides the event loop. You need to do this first because some other objects use it behind the scenes.
 * The topmost GUI interface element, or ''widget'', is the wx.Frame. All it consists of is an empty rectangular frame with a title bar. In all but this very basic example the frame would be sub-classed to allow the definition of further widgets and call-back functions within it.
 * The frame and its contents are not displayed automatically. You must explicitly call the Show() function.
 * The application needs to know which is the main frame.
 * At this point the application is visible on the screen but is not responding to events. You must call the Main Loop function to do this but note that once started the event loop never returns. Although no events have been defined explicitly there are some event handlers provided by wxPython. If you click on the X icon on the title bar the application receives a wx.ID_EXIT event that tells the application to terminate.
app.MainLoop()
}}}

 * The first thing to do in the main program is to create the wx.App object that provides the event loop. You need to do this first because some other objects use it behind the scenes. The `redirect=True` option

 * The topmost GUI interface element, or ''widget'', is the `wx.Frame`. All it consists of is an empty rectangular frame with a title bar. In all but this very basic example the frame would be sub-classed to allow the definition of further widgets and call-back functions within it.
 * The frame and its contents are not displayed automatically. You must explicitly call the `Show()` function.
 * At this point the application is visible on the screen but is not responding to events. You must call the `MainLoop` function to do this but note that once started the event loop never returns. Although no events have been defined explicitly there are some event handlers provided by wxPython. If you click on the X icon on the title bar the application receives a `wx.EVT_CLOSE` event that tells the application to terminate.

== Sub-Classing the Frame ==
It is common practice use an object-orientated approach as shown here. However, a procedural structure is equally valid and is shown in a subsequent section.
To develop this application further you need to add your own frame object before you can add functionality to the `wx.Frame`.

{{{
#!python
import wx

class Frame(wx.Frame):
    def __init__(self, title):
        wx.Frame.__init__(self, None, title=title, size=(350,200))

app = wx.App(redirect=True)
top = Frame("Hello World")
top.Show()
app.MainLoop()
}}}

If you are not very familiar with using objects in Python you should look closely at this example as sub-classing is used quite frequently in wxPython. In this example the Frame class is based on `wx.Frame`. Any functions that appear in the derived class will hide those of the same name in the base class. This commonly applies to the `__init__` function that is called automatically when a new object is defined. In this case the statement is `top = Frame("Hello World")`. It is necessary for the derived class to call the `__init__` function in the base class explicitly. Note that the first argument is `self` so that the base class knows what object is being initialized.

== Adding an Event Handler ==
{{{
#!python
class Frame(wx.Frame):
    def __init__(self, title):
        wx.Frame.__init__(self, None, title=title, size=(350,200))
        self.Bind(wx.EVT_CLOSE, self.OnClose)

    def OnClose(self, event):
        dlg = wx.MessageDialog(self,
            "Do you really want to close this application?",
            "Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
        result = dlg.ShowModal()
        dlg.Destroy()
        if result == wx.ID_OK:
            self.Destroy()
}}}

This example shows how to add a function that will handle the `wx.EVT_CLOSE` event that is generated when the user clicks on the X icon on the title bar of the frame. The `Bind()` function tells the event loop the name of the function to call when the event is detected. It is a useful convention to start the name of any event handlers with "On". This helps to ensure that the function name does not clash with one in the base class.

The `OnClose` function illustrates how to use a message dialog. The `ShowModal` function not only displays the dialog but also waits for the user to click on one of the buttons. The result is either `wx.ID_OK` or `wx.ID_CANCEL`. The Destroy function is used to terminate the application when the OK button is pressed. If `self.Close()` had been used instead of `self.Destroy()` the program would get into a loop as a further `wx.EVT_CLOSE` event would be issued.

== An Alternative Program Structure ==
Since there is only one `wx.Frame` object there is no need to sub-class it and you can write the whole program as a simple procedure. Since the event handler, `OnClose()` is no longer a member function of the frame object there is no `self` argument and so global variables are used instead.

{{{
#!python
import wx

def OnClose(event):
    dlg = wx.MessageDialog(top,
        "Do you really want to close this application?",
        "Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
    result = dlg.ShowModal()
    dlg.Destroy()
    if result == wx.ID_OK:
        top.Destroy()

app = wx.App(redirect=True)
top = wx.Frame(None, title="Hello World", size=(300,200))
top.Bind(wx.EVT_CLOSE, OnClose)
top.Show()
app.MainLoop()
}}}

== Adding Content to the Frame ==
This example shows how to add a menu bar, a status bar and a panel containing a button. The menu bar has only a single File menu but this is extended with a Help menu in the final example.

{{{
#!python
class Frame(wx.Frame):
    def __init__(self, title):
        wx.Frame.__init__(self, None, title=title, pos=(150,150), size=(350,200))
        self.Bind(wx.EVT_CLOSE, self.OnClose)

        menuBar = wx.MenuBar()
        menu = wx.Menu()
        m_exit = menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Close window and exit program.")
        self.Bind(wx.EVT_MENU, self.OnClose, m_exit)
        menuBar.Append(menu, "&File")
        self.SetMenuBar(menuBar)
        
        self.statusbar = self.CreateStatusBar()

        panel = wx.Panel(self)
        box = wx.BoxSizer(wx.VERTICAL)
        
        m_text = wx.StaticText(panel, -1, "Hello World!")
        m_text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
        m_text.SetSize(m_text.GetBestSize())
        box.Add(m_text, 0, wx.ALL, 10)
        
        m_close = wx.Button(panel, wx.ID_CLOSE, "Close")
        m_close.Bind(wx.EVT_BUTTON, self.OnClose)
        box.Add(m_close, 0, wx.ALL, 10)
        
        panel.SetSizer(box)
        panel.Layout()

}}}

-----

Learning wxPython by Example.

Contents

A Full Example

The following code shows an example of a wxPython application with a frame containing a menu bar, status bar and panel. The panel contains a label and a button that is bound to an exit function. The menu bar has a Help->About action that is bound to a dialog box. The dialog box shows how to display an HTML message and bring up a link in the user's default browser. You might find this example useful as a starting point that you can adapt. In a larger program it would be best to put the about box code into a separate file so that the main program file does not become too large. If this example is too large to start with then see the second example.

Toggle line numbers
   1 #!/usr/bin/python
   2 # -*- coding: <<encoding>> -*-
   3 #-------------------------------------------------------------------------------
   4 #   <<project>>
   5 # 
   6 #-------------------------------------------------------------------------------
   7 
   8 import wxversion
   9 wxversion.select("2.8")
  10 import wx, wx.html
  11 import sys
  12 
  13 aboutText = """<p>Sorry, there is no information about this program. It is
  14 running on version %(wxpy)s of <b>wxPython</b> and %(python)s of <b>Python</b>.
  15 See <a href="http://wiki.wxpython.org">wxPython Wiki</a></p>""" 
  16 
  17 class HtmlWindow(wx.html.HtmlWindow):
  18     def __init__(self, parent, id, size=(600,400)):
  19         wx.html.HtmlWindow.__init__(self,parent, id, size=size)
  20         if "gtk2" in wx.PlatformInfo:
  21             self.SetStandardFonts()
  22 
  23     def OnLinkClicked(self, link):
  24         wx.LaunchDefaultBrowser(link.GetHref())
  25         
  26 class AboutBox(wx.Dialog):
  27     def __init__(self):
  28         wx.Dialog.__init__(self, None, -1, "About <<project>>",
  29             style=wx.DEFAULT_DIALOG_STYLE|wx.THICK_FRAME|wx.RESIZE_BORDER|
  30                 wx.TAB_TRAVERSAL)
  31         hwin = HtmlWindow(self, -1, size=(400,200))
  32         vers = {}
  33         vers["python"] = sys.version.split()[0]
  34         vers["wxpy"] = wx.VERSION_STRING
  35         hwin.SetPage(aboutText % vers)
  36         btn = hwin.FindWindowById(wx.ID_OK)
  37         irep = hwin.GetInternalRepresentation()
  38         hwin.SetSize((irep.GetWidth()+25, irep.GetHeight()+10))
  39         self.SetClientSize(hwin.GetSize())
  40         self.CentreOnParent(wx.BOTH)
  41         self.SetFocus()
  42 
  43 class Frame(wx.Frame):
  44     def __init__(self, title):
  45         wx.Frame.__init__(self, None, title=title, pos=(150,150), size=(350,200))
  46         self.Bind(wx.EVT_CLOSE, self.OnClose)
  47 
  48         menuBar = wx.MenuBar()
  49         menu = wx.Menu()
  50         m_exit = menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Close window and exit program.")
  51         self.Bind(wx.EVT_MENU, self.OnClose, m_exit)
  52         menuBar.Append(menu, "&File")
  53         menu = wx.Menu()
  54         m_about = menu.Append(wx.ID_ABOUT, "&About", "Information about this program")
  55         self.Bind(wx.EVT_MENU, self.OnAbout, m_about)
  56         menuBar.Append(menu, "&Help")
  57         self.SetMenuBar(menuBar)
  58         
  59         self.statusbar = self.CreateStatusBar()
  60 
  61         panel = wx.Panel(self)
  62         box = wx.BoxSizer(wx.VERTICAL)
  63         
  64         m_text = wx.StaticText(panel, -1, "Hello World!")
  65         m_text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
  66         m_text.SetSize(m_text.GetBestSize())
  67         box.Add(m_text, 0, wx.ALL, 10)
  68         
  69         m_close = wx.Button(panel, wx.ID_CLOSE, "Close")
  70         m_close.Bind(wx.EVT_BUTTON, self.OnClose)
  71         box.Add(m_close, 0, wx.ALL, 10)
  72         
  73         panel.SetSizer(box)
  74         panel.Layout()
  75 
  76     def OnClose(self, event):
  77         dlg = wx.MessageDialog(self, 
  78             "Do you really want to close this application?",
  79             "Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
  80         result = dlg.ShowModal()
  81         dlg.Destroy()
  82         if result == wx.ID_OK:
  83             self.Destroy()
  84 
  85     def OnAbout(self, event):
  86         dlg = AboutBox()
  87         dlg.ShowModal()
  88         dlg.Destroy()  
  89 
  90 app = wx.App(redirect=True)   # Error messages go to popup window
  91 top = Frame("<<project>>")
  92 top.Show()
  93 app.MainLoop()

A Bare-Bones Application

The following is a minimum wxPython application in the tradition of Hello World:

Toggle line numbers
   1 import wx
   2 
   3 app = wx.App(redirect=True)
   4 top = wx.Frame(None, title="Hello World", size=(300,200))
   5 top.Show()
   6 app.MainLoop()
  • The first thing to do in the main program is to create the wx.App object that provides the event loop. You need to do this first because some other objects use it behind the scenes. The redirect=True option

  • The topmost GUI interface element, or widget, is the wx.Frame. All it consists of is an empty rectangular frame with a title bar. In all but this very basic example the frame would be sub-classed to allow the definition of further widgets and call-back functions within it.

  • The frame and its contents are not displayed automatically. You must explicitly call the Show() function.

  • At this point the application is visible on the screen but is not responding to events. You must call the MainLoop function to do this but note that once started the event loop never returns. Although no events have been defined explicitly there are some event handlers provided by wxPython. If you click on the X icon on the title bar the application receives a wx.EVT_CLOSE event that tells the application to terminate.

Sub-Classing the Frame

It is common practice use an object-orientated approach as shown here. However, a procedural structure is equally valid and is shown in a subsequent section. To develop this application further you need to add your own frame object before you can add functionality to the wx.Frame.

Toggle line numbers
   1 import wx
   2 
   3 class Frame(wx.Frame):
   4     def __init__(self, title):
   5         wx.Frame.__init__(self, None, title=title, size=(350,200))
   6 
   7 app = wx.App(redirect=True)
   8 top = Frame("Hello World")
   9 top.Show()
  10 app.MainLoop()

If you are not very familiar with using objects in Python you should look closely at this example as sub-classing is used quite frequently in wxPython. In this example the Frame class is based on wx.Frame. Any functions that appear in the derived class will hide those of the same name in the base class. This commonly applies to the __init__ function that is called automatically when a new object is defined. In this case the statement is top = Frame("Hello World"). It is necessary for the derived class to call the __init__ function in the base class explicitly. Note that the first argument is self so that the base class knows what object is being initialized.

Adding an Event Handler

Toggle line numbers
   1 class Frame(wx.Frame):
   2     def __init__(self, title):
   3         wx.Frame.__init__(self, None, title=title, size=(350,200))
   4         self.Bind(wx.EVT_CLOSE, self.OnClose)
   5 
   6     def OnClose(self, event):
   7         dlg = wx.MessageDialog(self, 
   8             "Do you really want to close this application?",
   9             "Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
  10         result = dlg.ShowModal()
  11         dlg.Destroy()
  12         if result == wx.ID_OK:
  13             self.Destroy()

This example shows how to add a function that will handle the wx.EVT_CLOSE event that is generated when the user clicks on the X icon on the title bar of the frame. The Bind() function tells the event loop the name of the function to call when the event is detected. It is a useful convention to start the name of any event handlers with "On". This helps to ensure that the function name does not clash with one in the base class.

The OnClose function illustrates how to use a message dialog. The ShowModal function not only displays the dialog but also waits for the user to click on one of the buttons. The result is either wx.ID_OK or wx.ID_CANCEL. The Destroy function is used to terminate the application when the OK button is pressed. If self.Close() had been used instead of self.Destroy() the program would get into a loop as a further wx.EVT_CLOSE event would be issued.

An Alternative Program Structure

Since there is only one wx.Frame object there is no need to sub-class it and you can write the whole program as a simple procedure. Since the event handler, OnClose() is no longer a member function of the frame object there is no self argument and so global variables are used instead.

Toggle line numbers
   1 import wx
   2 
   3 def OnClose(event):
   4     dlg = wx.MessageDialog(top, 
   5         "Do you really want to close this application?",
   6         "Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
   7     result = dlg.ShowModal()
   8     dlg.Destroy()
   9     if result == wx.ID_OK:
  10         top.Destroy()
  11 
  12 app = wx.App(redirect=True)
  13 top = wx.Frame(None, title="Hello World", size=(300,200))
  14 top.Bind(wx.EVT_CLOSE, OnClose)
  15 top.Show()
  16 app.MainLoop()

Adding Content to the Frame

This example shows how to add a menu bar, a status bar and a panel containing a button. The menu bar has only a single File menu but this is extended with a Help menu in the final example.

Toggle line numbers
   1 class Frame(wx.Frame):
   2     def __init__(self, title):
   3         wx.Frame.__init__(self, None, title=title, pos=(150,150), size=(350,200))
   4         self.Bind(wx.EVT_CLOSE, self.OnClose)
   5 
   6         menuBar = wx.MenuBar()
   7         menu = wx.Menu()
   8         m_exit = menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Close window and exit program.")
   9         self.Bind(wx.EVT_MENU, self.OnClose, m_exit)
  10         menuBar.Append(menu, "&File")
  11         self.SetMenuBar(menuBar)
  12         
  13         self.statusbar = self.CreateStatusBar()
  14 
  15         panel = wx.Panel(self)
  16         box = wx.BoxSizer(wx.VERTICAL)
  17         
  18         m_text = wx.StaticText(panel, -1, "Hello World!")
  19         m_text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
  20         m_text.SetSize(m_text.GetBestSize())
  21         box.Add(m_text, 0, wx.ALL, 10)
  22         
  23         m_close = wx.Button(panel, wx.ID_CLOSE, "Close")
  24         m_close.Bind(wx.EVT_BUTTON, self.OnClose)
  25         box.Add(m_close, 0, wx.ALL, 10)
  26         
  27         panel.SetSizer(box)
  28         panel.Layout()


The full example is based on the wxPython template that is used in the Luke-SDK IDE.

wxPython by Example (last edited 2012-06-28 08:10:48 by SWM-HIGH-SPEED2-22)

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