Size: 3175
Comment: missing edit-log entry for this revision
|
Size: 8136
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
How to learn wxPython. | = Learning wxPython by Example. = |
Line 3: | Line 3: |
We have had a lot of questions on the newsgroup asking how to go about learning wxPython. this page gives some pointers on how to do just that. |
== The Full Example == |
Line 6: | Line 5: |
First of all, if you are new to Python, and especially if you are new to programming in general, it makes the most sense to learn Python itself first, without any GUI stuff. This can be frustrating if your goal is to write GUI programs, and particularly if you have experience with an environment like Visual Basic in which GUI programming is integrated into the environment. It is worth it, however, to take some time to learn about Python. Python is a very powerful language capable of doing many things both with and without GUIs. |
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. |
Line 15: | Line 7: |
Using wxPython requires a pretty good understanding of Object Oriented (OO) programming in Python, and all of the tutorials and references that I will refer to later assume this knowledge. |
{{{ #!/usr/bin/python # -*- coding: <<encoding>> -*- #------------------------------------------------------------------------------- # <<project>> # #------------------------------------------------------------------------------- |
Line 19: | Line 15: |
To learn Python, go to the Python for Beginners page at the main Python web site: |
import wxversion wxversion.select("2.8") import wx, wx.html import sys |
Line 22: | Line 20: |
http://www.python.org/doc/Newbies.html | aboutText = """<p>Sorry, there is no information about this program. It is running on version %(wxpy)s of <b>wxPython</b> and %(python)s of <b>Python</b>. See <a href="http://wiki.wxpython.org">wxPython Wiki</a></p>""" |
Line 24: | Line 24: |
Follow the links on that page, and you should find something to your liking. |
class HtmlWindow(wx.html.HtmlWindow): def __init__(self, parent, id, size=(600,400)): wx.html.HtmlWindow.__init__(self,parent, id, size=size) if "gtk2" in wx.PlatformInfo: self.SetStandardFonts() |
Line 27: | Line 30: |
Once you have a fundamental understanding of programming in Python, you can start to learn wxPython for GUI programming. |
def OnLinkClicked(self, link): wx.LaunchDefaultBrowser(link.GetHref()) class AboutBox(wx.Dialog): def __init__(self): wx.Dialog.__init__(self, None, -1, "About <<project>>", style=wx.DEFAULT_DIALOG_STYLE|wx.THICK_FRAME|wx.RESIZE_BORDER| wx.TAB_TRAVERSAL) hwin = HtmlWindow(self, -1, size=(400,200)) vers = {} vers["python"] = sys.version.split()[0] vers["wxpy"] = wx.VERSION_STRING hwin.SetPage(aboutText % vers) btn = hwin.FindWindowById(wx.ID_OK) irep = hwin.GetInternalRepresentation() hwin.SetSize((irep.GetWidth()+25, irep.GetHeight()+10)) self.SetClientSize(hwin.GetSize()) self.CentreOnParent(wx.BOTH) self.SetFocus() |
Line 30: | Line 50: |
I would suggest starting with the Tutorial. It is brief, and not complete, but it is a good start. You can find it here: |
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) |
Line 33: | Line 55: |
http://wxpython.org/tutorial.php | 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") menu = wx.Menu() m_about = menu.Append(wx.ID_ABOUT, "&About", "Information about this program") self.Bind(wx.EVT_MENU, self.OnAbout, m_about) menuBar.Append(menu, "&Help") self.SetMenuBar(menuBar) self.statusbar = self.CreateStatusBar() |
Line 35: | Line 68: |
Once you have gone through that, you might want to go through the wxpython wiki getting started section: |
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() |
Line 38: | Line 83: |
http://wiki.wxpython.org/index.cgi/Getting_20Started | 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() |
Line 40: | Line 92: |
Between these two, you should have a basic grasp of how wxPython works, and be ready to make you own application. To so this, you will want two things: examples and a reference. |
def OnAbout(self, event): dlg = AboutBox() dlg.ShowModal() dlg.Destroy() |
Line 44: | Line 97: |
The wxPython demo is your best source of examples. It is distributed with wxPython, and demonstrates virtually all the features of wxPython. When you run it, you can see how different features work, and see the source code that made it happen. Many of us look for something in the demo that is close to what we want to do, copy it, and then alter it to fit our needs. |
app = wx.App(redirect=True) # Error messages go to popup window top = Frame("<<project>>") top.Show() app.SetTopWindow(top) app.MainLoop() }}} |
Line 51: | Line 104: |
Another source of examples is the wxPython cookbook: | == A Bare-Bones Example == |
Line 53: | Line 106: |
http://wiki.wxpython.org/index.cgi/wxPython_20Cookbook | The following is a minimum wxPython application in the tradition of Hello World: |
Line 55: | Line 108: |
{{{ import wx |
|
Line 56: | Line 111: |
The reference manual for wxPython is the same as the reference for the C++ version of wxWindows, and can be found here: |
app = wx.App(redirect=True) top = wx.Frame(None, title="Hello World", size=(300,200)) top.Show() app.SetTopWindow(top) app.MainLoop() }}} |
Line 59: | Line 118: |
http://www.wxpython.org/onlinedocs.php | * 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 |
Line 61: | Line 120: |
It is written in C++ syntax, with notes inserted for when the Python implementation differs from the C++. The fact that the docs are written for C++ is unfortunate, not because they aren't useful to Python programmers, but because is can be very intimidating to new users who don't know C++. In fact, many Python programmers who don't know a bit of C++ find that the docs can be very useful. It only takes a little while to learn to translate form the C++ in the docs to the equivalent Python. One of the best way to learn to do this is to compare code form the examples n the wxPython demo to what is in the reference manual. |
* 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.EVT_CLOSE event that tells the application to terminate. |
Line 71: | Line 125: |
[NOTE: it would be great if someone would add a section here with examples of how to translate from C++ to Python.] |
== Sub-Classing the Frame == To develop this application further you need to add your own frame object before you can add functionality to the wx.Frame. |
Line 74: | Line 128: |
{{{ import wx |
|
Line 75: | Line 131: |
class Frame(wx.Frame): def __init__(self, title): wx.Frame.__init__(self, None, title=title, size=(350,200)) |
|
Line 76: | Line 135: |
app = wx.App(redirect=True) top = Frame("Hello World") top.Show() app.SetTopWindow(top) 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 == {{{ 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 On Close 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. ---- The full example is based on the wxPython template that is used in the [[http://luke-sdk.berlios.de|Luke-SDK ]] IDE. |
Learning wxPython by Example.
The 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.
# -*- coding: <<encoding>> -*- #------------------------------------------------------------------------------- # <<project>> # #------------------------------------------------------------------------------- import wxversion wxversion.select("2.8") import wx, wx.html import sys aboutText = """<p>Sorry, there is no information about this program. It is running on version %(wxpy)s of <b>wxPython</b> and %(python)s of <b>Python</b>. See <a href="http://wiki.wxpython.org">wxPython Wiki</a></p>""" class HtmlWindow(wx.html.HtmlWindow): def __init__(self, parent, id, size=(600,400)): wx.html.HtmlWindow.__init__(self,parent, id, size=size) if "gtk2" in wx.PlatformInfo: self.SetStandardFonts() def OnLinkClicked(self, link): wx.LaunchDefaultBrowser(link.GetHref()) class AboutBox(wx.Dialog): def __init__(self): wx.Dialog.__init__(self, None, -1, "About <<project>>", style=wx.DEFAULT_DIALOG_STYLE|wx.THICK_FRAME|wx.RESIZE_BORDER| wx.TAB_TRAVERSAL) hwin = HtmlWindow(self, -1, size=(400,200)) vers = {} vers["python"] = sys.version.split()[0] vers["wxpy"] = wx.VERSION_STRING hwin.SetPage(aboutText % vers) btn = hwin.FindWindowById(wx.ID_OK) irep = hwin.GetInternalRepresentation() hwin.SetSize((irep.GetWidth()+25, irep.GetHeight()+10)) self.SetClientSize(hwin.GetSize()) self.CentreOnParent(wx.BOTH) self.SetFocus() 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") menu = wx.Menu() m_about = menu.Append(wx.ID_ABOUT, "&About", "Information about this program") self.Bind(wx.EVT_MENU, self.OnAbout, m_about) menuBar.Append(menu, "&Help") 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() 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() def OnAbout(self, event): dlg = AboutBox() dlg.ShowModal() dlg.Destroy() app = wx.App(redirect=True) # Error messages go to popup window top = Frame("<<project>>") top.Show() app.SetTopWindow(top) app.MainLoop()
A Bare-Bones Example
The following is a minimum wxPython application in the tradition of Hello World:
import wx app = wx.App(redirect=True) top = wx.Frame(None, title="Hello World", size=(300,200)) top.Show() 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 "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.
- 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.EVT_CLOSE event that tells the application to terminate.
Sub-Classing the Frame
To develop this application further you need to add your own frame object before you can add functionality to the wx.Frame.
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.SetTopWindow(top) 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
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 On Close 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.
The full example is based on the wxPython template that is used in the Luke-SDK IDE.