|Last modified: 14-09-2022|
wxWidgets, formerly known as wxWindows, is an open-source, cross-platform framework which uses the target OS' native widgets to achieve native look and feel. wxPython is a thin layer above the wxWidgets framework.
Being a thin layer above the OS' GUI, it loads faster than Tkinter; It also offers a rich set of widgets, and seems easier to use, at the expense of having to install an extra package while Tkinter is part of the Python package.
Phoenix/wxPython 4 is a rewrite of wxPython for Python3. To install wxPython, simply, run "pip install wxpython".
As of 2022, besides online resources, Michael Driscoll's "Creating GUI Applications with wxPython", published in 2020, seems the only book worth recommending today as it matches the "Project Phoenix" rewrite of wxPython: "wxPython in Action" was published in 2006; "wxPython Application Development Cookbook" and "wxPython Recipes" have quite negative user comments.
The wxPython Demo shows the different widgets available.
If you work under Windows, you can either install the standard release of Python, or ActiveState's version of Python (It includes Python as available on www.python.org, Windows-specific add-on's like access to the Win32 API and COM, along with a few other items like BerkeleyDB.) The Enthought version includes a lot of stuff that are probably not useful to most developers, but you might need those. FWIW, the so-called "Python IDE" that comes with ActiveState is just a graphical command-line interface to Python; Nothing like rich IDE's like Delphi or VB. You may need to add the path to the Python folder to the PATH environment variable.
Once Python is installed, install wxPython. It contains wxWidgets, so you don't need to download both. Make sure you download the wxPython package that matches the version of Python that you installed previously, eg. 2.4.x or 2.5.x (the wxPython installer will tell you if it can't find the right version anyway.) As an option, you can download the documentation and demos from the site. In Windows Explorer, double-click on "C:\Program Files\wxPython2.6 Docs and Demos\demo\demo.py" to run the demo.
If you choose to use UltraEdit to work with Python and want to add support for syntax highlighting, wordfiles are available on the site for various versions of Python. As alternate IDE's built for Python, take at look at Stani's Python Editor (SPE; It includes the wxGlade GUI designer), ActiveState's Komodo, Wing IDE Pro (commercial), PyCharm (commercial), Visual Studio Code (open source), PyScripter (open source)
Demos (wxPython-demo-x.tar.gz) can be downloaded here.
To check which version of wxPython is currently installed:
"When most people look at this running program, they see something they would call a “window.” However, wxPython does not call this a window. It calls this a “frame.” In wxPython,“window” is the generic term for any object that displays on the screen (what other toolkits might call a “widget”). So, a wxPython programmer will often refer to objects such as buttons or text boxes as “windows.” This may seem confusing, but the usage dates to the earliest days of the original C++ toolkit, and it’s unlikely to change now. In this book, we’ll try to avoid the use of window as a generic term, because it’s confusing and also because it’s the name of a big product from a major corporation. We’ll use widget as the generic term. When we’re specifically referring to the operating system of similar name, we’ll do it with a capital “W.”"
Use a frame when you need a window for your application; Use a panel (within that frame) to place other widgets onto. Don't place (most) widgets right onto the frame itself; there are some problems with that. You can and often will use multiple panels within the same frame.
As an easy way to lay down widgets into a frame, use the wx*Sizer classes (those are the most common):
wxApp -> wxFrame -> wxPanel -> wxSizer -> wxControl
wxPython-speak for what is otherwise known in the Windows world as the tab widget, ie. multiple sub-windows on top of each other.
First, the obligatory "Hello, world!":
This can be used to launch a script when the user clicks on the button, and display information in the label:
Next, a basic editor (from wxPython for newbies):
Here's how to add a menu bar, and display a dialogbox when choosing an item:
Here, we'll build a filled window that contains a plane, ie. not just an empty frame, and add widgets on the plane:
Note: This book came out in 2006; There might be parts that are no longer relevant, but a newbie can't tell
Two objects are required in all wxPython applications.: The application object, which manages the event loop and oversees the application lifecycle; The top-level window, which is the focal point of user interaction with your program.
What we generally call a window in Windows is called a frame in wxWidgets. In wxWidgets, windows refer to any widget within a frame.
A bare frame:
A more real-life structure:
If the application is so simple as to only need a single frame, there's an easier way to create an application:
A frame cannot be created before the application object.
The most important use of ID numbers in wxPython is to create a unique relationship between an event that happens to a specific object and a function which is called in response to that event.
In real-life applications, widgets such as push-buttons are not created directly in a frame, but rather in a panel, which acts as a container and is itself created in a frame. A panel usually overlays the entire frame, and helps keeping the widgets separate from the toolbar and status bar. When a frame is created with just a single child window, that child window (typically, a panel) is automatically resized to fill the client area of the frame.
Use a sizer to avoid having to specify the position and size of each widget, including when the user resizes the frame/panel.
Common dialogs are available. Here's an example:
If you just need some basic, text input from the user:
If you want to have the user pick an item in a limited list:
Events are represented as instances of the wx.Event class and its subclasses, such as wx.CommandEvent and wx.MouseEvent. An event handler is a written function or method that is called in response to an event. Also called a handler function or handler method. An event binder is a wxPython object that encapsulates the relationship between a specific widget, a specific event type, and an event handler. In order to be invoked, all event handlers must be registered with an event binder.
PyCrust is a graphical shell program, written in wxPython, that you can use to help analyze your wxPython programs. PyCrust is part of a larger Py package that includes additional programs with related functionality including PyFilling, PyAlaMode, PyAlaCarte, and PyShell.
The key to a successful MVC design is not in making sure that every object knows about every other object. Instead, a successful MVC program explicitly hides knowledge about one part of the program from the other parts. The goal is for the systems to interact minimally, and over a well-defined set of methods. In particular, the Model component should be completely isolated from the View and Controller.
Because both refactoring and the use of an MVC design pattern tend to break your program into smaller pieces, it is easier for you to write specific unit tests targeting individual parts of your program. Since version 2.1, Python has been distributed with the unittest module. The unittest module implements a test framework called PyUnit.
The layout mechanism in wxPython is called a sizer, and the idea is similar to layout managers in Java AWT and other interface toolkits. Each different sizer manages the size and position of its windows based on a set of rules. The sizer belongs to a container window (typically a wx.Panel). Subwindows created inside the parent must be added to the sizer, and the sizer manages the size and position of each widget.
The primary wx.Frame class has several different frame style bits which can change its appearance. In addition, wxPython offers miniframes, and frames that implement the Multiple Document Interface (MDI). Frames can be split into sections using splitter bars, and can encompass panels larger than the frame itself using scrollbars.
A panel is an instance of the class wx.Panel, and is a simple container for other widgets with little functionality of its own. You should almost always use a wx.Panel as the top-level subwidget of your frame. For one thing, the extra level can allow greater code reuse, as the same panel and layout could be used in more than one frame. Using a wx.Panel gives you some of the functionality of a dialog box within the frame. This functionality manifests itself in a couple of ways. One is simply that wx.Panel instances have a different default background color under MS Windows operating systems—white, instead of gray. Secondly, panels can have a default item that is automatically activated when the Enter key is pressed, and panels respond to keyboard events to tab through the items or select the default item in much the same way that a dialog does.
Here's how to create an MDI parent/child interface:
A splitter window is a particular kind of container widget that manages exactly two sub-windows. The two sub-windows can be stacked horizontally or next to each other left and right. In between the two sub-windows is a sash, which is a movable border that changes the size of the two sub-windows. Splitter windows are often used for sidebars to the main window (i.e., a browser).
In wxPython, a wizard is a series of pages controlled by an instance of the class wx.wizard.Wizard. The wizard instance manages the events that take the user through the pages. The pages themselves are instances of either the class wx.wizard.WizardPageSimple or wx.wizard.WizardPage. In both cases, they are merely wx.Panel instances with the additional logic needed to manage the page chain.
A validator is a special wxPython object that simplifies managing data in a dialog. A validator is attached to a specific widget in your system.
The recommended way to deal with complicated layout these days is by using a sizer. A sizer is an automated algorithm for laying out a group of widgets. A sizer is attached to a container, usually a frame or panel. Subwidgets that are created within a parent container must be separately added to the sizer. When the sizer is attached to the container, it then manages the layout of the children contained inside it. The most flexible sizers, the grid bag and box, will be able to do nearly everything you’ll want them to. A wxPython sizer is an object whose sole purpose is to manage the layout of a set of widgets within a container. The sizer is not a container or a widget itself. It is just the representation of an algorithm for laying out a screen.
Phoenix was the code name for the Python 3 port of wxPython. The previous versions of wxPython are not completely compatible with wxPython 4.
The wx.Frame is the window object that contains all the other widgets. The Panel is a container that also enables the ability to tab between widgets. You can use Panels to group widgets as well.
A most basic app:
To make code more modular, most code is put in classes: The frame class for widgets related to the frame, and the panel class for those grouped into a panel.
A panel should have a parent, which in this case is a Frame. You only want one panel as the sole widget for a frame. The panel will automatically expand to fill the frame as well if it is the only child widget of the frame. wx.Panel widgets enable tabbing between widgets on Windows. So if you want to be able to tab through the widgets in a form you have created, you are required to have a panel as their parent.
Here's how to add a push button:
wxPython supports both absolute positioning of widgets and relative positioning of widgets. Relative positioning of widgets requires the use of special container objects called Sizers or Layouts. A sizer allows you to resize your application and have the widgets resize along with it. It is always recommended that you use sizers as they will make your application much nicer to use on multiple displays and screen sizes.
The wxPython toolkit has several sizers:
Adding the button to the sizer:
The book goes on showing different how to write different applications (an image viewer, a database viewer+editor, a calculator, etc.)
Read Which is the best compiler to use with wxWindows 2? to check which compiler you'd rather work with if you are just getting started. A list of C compilers can be found here.
Just run the Windows installer, which will take care of uninstalling the current version, if need be.
Both widgets are located in the same frame. Why use self.button?
Rename the script from .py to .pyw.
"The sizers are a basic tool in wxWidgets to get layouts to be mostly portable to other platforms where the widgets may be of different size. They are less important if you plan to develop for only one platform but its useful to get used to them as they can also aid when adding/removing elements from the design."