You'll feel much better after reading about this new cross-platform toolkit written in Python and wrapped around wxWindows.
by Hugues Talbot
To many people in the ``real world'', MS Windows is an inescapable, however unfortunate, fact of life. Some of these people might even have clients or bosses who require a ``standard'' Windows GUI application at the end of the day. For many developers, being able to choose the best tool for the task at hand, rather than being told which one to use, is an essential element of their quality of life, and Linux is a pleasant development environment.
It is in fact now possible to do quality, rapid GUI development for Windows on Linux, and is becoming increasingly possible for other GUI systems as well, such as Apple Macintosh, BeOS or OS/2. One of these tools, which I present in this article, is wxPython, which is not only based upon a proven toolkit, wxWindows, but uses our favorite language, Python.
There is no lack of choice of GUI development systems or toolkits under Linux, and quite a few of them can be called portable, i.e., work on at least two different platforms, for example, Linux/UNIX+X11 and Windows. Many of them are free, but not all of them are in usable form (i.e., documented, maintained, relatively bug-free and feature-rich). However, we are fortunate that such tools do exist. In fact, a well-maintained web page, http://www.free-soft.org/guitool/, lists an impressive number of such toolkits. The problem is deciding which one to choose, since life is too short to try them all.
The interface of wxWindows to Python is remarkably transparent. The concepts are the same and the naming conventions are mostly the same. The object-oriented nature of the toolkit has been preserved. If you know how to program in C++ with wxWindows, you will have no problem with wxPython. Conversely, if you have a working proof of concept in wxPython, porting all or part of it to C++ for better speed should be straightforward.
wxPython is quite compact, but doesn't come with the standard Python distribution. See the Resources section on where to get the software. I found wxPython easy to learn; the distribution comes with a huge series of helpful demos which I will use in examples.
All of wxPython is open source, so people can contribute and fix bugs. In general, the software quality is high.
The documentation is both very complete and almost non-existent. Robin can get away with this because wxPython is so similar to wxWindows that the wxWindows documentation, which is quite good and complete, can be used instead. The Python-specific part of the documentation is reduced to a small number of notes within the text (if a feature is not available or slightly different, for example) and a small section toward the end of the documentation. It is hardly any effort to do the mental translation from C++-type calls to Python, but if you've never seen C++ code in your life, this can be seriously off-putting.
The product is still very much in development. It follows wxGTK quite closely, but the wxGTK version it is based on is an unstable, development version. This means a number of things may not work perfectly, and things are likely to change a lot from version to version. I've had a lot of problems with printing under Linux, whereas it works perfectly under Windows.
wxPython would probably benefit greatly from a step-by-step tutorial. By the time you read this, someone will most likely have written one.
An interactive GUI-building tool would also be of interest. I understand that reusing the one from wxWindows should become possible soon.
The installation of wxPython is fairly straightforward if you have a Debian or an RPM-based system, as Robin Dunn provides both of these packages on his web page at http://wxpython.org/. You'll need wxGTK installed (again, a package is provided) as well as Mesa-3.0.
We are now going to look at some simple wxPython examples. The intention is not to offer a tutorial but to get a feel for the way wxPython can be used.
Note the systematic use of the object-oriented framework even in this very simple example. The frame and the application are subclasses of the pre-defined classes. We need to redefine only the methods we use to get our program working. A screen shot of this impressive application is shown in Figure 1.
One might say that about 40 lines of code is too many for a simple application that basically does nothing. In fact, you could probably cut this down to a few lines, but the goal is to present a relatively well-structured piece of code which is easy to build upon.
There are many function calls with -1 given as second argument, such as panel = wxPanel(self, -1). In these cases, the value of -1 is a mandatory numerical identifier for the object being created, which is used when connecting widgets together, as we will see in the second example. A value of -1 means ``default'' and is useful when this object ID will not be used anywhere in the code.
On line 47, we associate the application close event with the OnCloseWindow method, defined on line 76. Using this method, we build a quick message dialog box to ask the user for confirmation. On lines 48-64, we create a status line where the menu tool tips will be displayed. The main menu of applications is defined by the specs in myMenuTable, lines 20-25. Note that the ``New'' menu item will also call the method of line 81. In the definition of the menu items (lines 24-29), the character & before a letter indicates a keyboard shortcut (typing ALT + the letter calls the menu item).
On lines 65-67, we make the window layout fit together and set the autofit feature of the wxBoxSizer objects ``on''. Lines 69-72 define the callback method from both the menu item and the button. This method simply redefines the text content of the static text object defined on line 31. Pressing the button multiple times shows the strings defined in self.myFortunes, line 13-18, in succession. The method of lines 87-88 is called from the ``Exit'' menu item and invokes the Close event, which will close the application. Lines 90-106 are identical to the ``hello'' example. A screen shot of this application is shown in Figure 2.
The more interesting points of this ``toy'' application are how window layout can be achieved (using wxBoxSizer) and how events and widgets are connected (using EVT_MENU and EVT_BUTTON in this case). In fact, as it is, only the layout of the button is satisfactory; the main text is still in a fixed position--a complete solution would be too long to show here.
Note the use of the self.something variables. If a variable is to be accessed across methods, it must be called in this way (self being the object instance). If a variable is private to a method, the self prefix is not necessary.
At the moment, we are enjoying a growing array of usable tool kits, and I feel wxPython is one of the better ones. Like most things written in Python, programs in wxPython tend to be compact, easy-to-read and maintain and powerful. The range of available widgets doesn't match MFCs (Microsoft foundation classes), but is adequate for most applications. I personally find that this particular tool kit makes the RAD (rapid application development) concept finally available to Linux. The fact that applications written in this framework also work on Windows will be a tremendous benefit for some.
As it stands, wxPython probably cannot replace Tkinter as the default Python GUI tool, at least not until the Apple Macintosh port of wxWindows is completed and a stable release is made. But it shows a lot of promise, as being a much higher-level toolkit.
Hugues Talbot (hugues.talbot@cmis.csiro.au) is a Frenchman living in Australia. As such, he likes to eat, drink, cook and annoy his colleagues. His wife is constantly reminding him to get a hobby that has nothing to do with computing.