wxPython: Creating GUIs with Python

2

wxPython is a cross-platform GUI toolkit for Python programming language. It was developed by Robin Dunn along with Harri Pasanen and Edward Zimmerman in 1995. wxPython helps to create robust graphical user interfaces which can be customized depending upon the use case. Its easy, user-friendly, and simple to understand.

It is implemented as a set of Python extension modules that wrap the GUI components of the popular wxWidgets cross-platform library, which is written in C++. It is one of the alternatives to the Tkinter framework that comes built into the Python standard library.

It’s free and Open Source. wxPython is cross-platform which means the program can run on several platforms without changing the source code of the original program. Currently, supported platforms include Microsoft Windows, Mac OS X, and macOS, and Linux or other UNIX-like systems with GTK2 or GTK3 libraries.

Also Read: Tkinter Tutorial – Drawing a Line Using Tkinter Canvas

Creating a Keypad GUI application with wxPython

To understand it better, let’s try to create a small application using wxPython. The code for this application is very easy to read. The application uses wxObject Classes that serve as the base classes for all the classes in the WxPython API.

Content Structure

  1. Application Code Breakdown
  2. The Complete Application
  3. Output
  4. Conclusion

Creating GUI with wxPython – Step-By-Step

  • Installing wxPython
pip install wxPython
  • Importing wxPython
import wx
  • Creating a wxPython Application and assigning it to the variable “app”
app = wx.App()
  • Creating a Class “Window” containing which would inherit all the properties and methods of the wx.Frame object coming from the wxPython API

Code:

class Window(wx.Frame):

Explanation:

A frame is a window whose size and position can be changed by the user. It is to be used as an input form. It usually consists of a title bar and has thick borders. It can optionally contain a menu bar, toolbar, and status bar as per the application requirement. It is by default resizable. Any controls for the application should not be created as its children since the controls will be handled by using wx.Panel in the following code.

  • __init__ () Constructor Function

Code:

# Defining the default Constructor function
    def __init__(self, title):
        super().__init__(parent=None, title=title)

        # Create a panel
        self.panel = wx.Panel(self)

Explanation:

First, we define our constructor function. The only default parameter defined for the init function is the title for our application window which would accept an argument later in the code. wx.Panel contains all the controls for our application window. It should be created as the sole child of the frame, and it serves as the parent of the actual controls. The frame will size the panel so that it always fills the client area.

  • wx.GridBagSizer()

Code:

# Define the grid sizer for our layout
        sizer = wx.GridBagSizer(4, 3)

Explanation:

Next, we are defining a sizer for our window layout using wx.GridBagSizer(4,3). It can lay out items in a virtual grid and takes optional arguments specifying the gap between rows and columns in pixels. The total size of the virtual grid is determined by the largest row and column that items are positioned at, adjusted for spanning.

  • sizer.Add()

Code:

# Defining layout components
        sizer.Add(
            wx.StaticText(self.panel, label="My Keypad"),
            pos=(0, 1),
            flag=wx.ALIGN_CENTER,
        )

        sizer.Add(wx.Button(self.panel, label="1"), pos=(1, 0), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="2"), pos=(1, 1), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="3"), pos=(1, 2), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="4"), pos=(2, 0), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="5"), pos=(2, 1), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="6"), pos=(2, 2), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="7"), pos=(3, 0), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="8"), pos=(3, 1), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="9"), pos=(3, 2), flag=wx.EXPAND)

        sizer.Add(wx.Button(self.panel, label="*"), pos=(4, 0), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="0"), pos=(4, 1), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="#"), pos=(4, 2), flag=wx.EXPAND)

Explanation:

Further in the code, we start adding content to our application using the sizer variable that we defined earlier. sizer.Add() adds an item to the sizer at the grid cell with pos=(0, 1) specifying the row and column position to define the label “My Keypad” for our panel using the wx.StaticText Constructor. wx.ALIGN_CENTER is the alignment enumeration centring our label text as a flag.

Next, we are adding buttons to the layout of our application with all the texts as a calculator using the wx.Button Constructor. The row and column position for each of the buttons has to be specified too like above. And finally the wx.EXPAND ensures the expansion of the individual elements taking the entire space available for the layout.

  • sizer.AddGrowableRow(), sizer.AddGrowableCol(), SetSizer(sizer)

Code:

        sizer.AddGrowableRow(0)
        sizer.AddGrowableRow(1)
        sizer.AddGrowableRow(2)
        sizer.AddGrowableRow(3)
        sizer.AddGrowableRow(4)

        sizer.AddGrowableCol(0)
        sizer.AddGrowableCol(1)
        sizer.AddGrowableCol(2)

         self.panel.SetSizer(sizer)

Explanation:

sizer.AddGrowableRow() specifies that the row index (starting from zero) should be grown if there is extra space available to the sizer and sizer.AddGrowableCol() specifies that the column index (starting from zero) should be grown if there is extra space available to the sizer.

Then, the  SetSizer(sizer) is set to the panel window, with all the layout details and specifications.

  • Center(), Show(), Window() and app.MainLoop()

Code:

self.Center()  
self.Show()  

window = Window("WxPython GUI Application Demo")
  
app.MainLoop()

Explanation:

Center() displays the window to the screen’s center, Show() shows the constructed frame, Window() sets the title for the application and the app.MainLoop() triggers the application initializing the GUI event loop for the program. 

Complete Code For Creating GUI with the wxPython Module

Code:

# Create wxPython Application
app = wx.App()

class Window(wx.Frame):
    # Defining the Default Constructor function
    def __init__(self, title):
        super().__init__(parent=None, title=title)

        # Create a panel
        self.panel = wx.Panel(self)

        # Define Grid
        sizer = wx.GridBagSizer(4, 3)

        sizer.Add(
            wx.StaticText(self.panel, label="My Keypad"),
            pos=(0, 1),
            flag=wx.ALIGN_CENTER,
        )

        sizer.Add(wx.Button(self.panel, label="1"), pos=(1, 0), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="2"), pos=(1, 1), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="3"), pos=(1, 2), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="4"), pos=(2, 0), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="5"), pos=(2, 1), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="6"), pos=(2, 2), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="7"), pos=(3, 0), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="8"), pos=(3, 1), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="9"), pos=(3, 2), flag=wx.EXPAND)

        sizer.Add(wx.Button(self.panel, label="*"), pos=(4, 0), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="0"), pos=(4, 1), flag=wx.EXPAND)
        sizer.Add(wx.Button(self.panel, label="#"), pos=(4, 2), flag=wx.EXPAND)

        sizer.AddGrowableRow(0)
        sizer.AddGrowableRow(1)
        sizer.AddGrowableRow(2)
        sizer.AddGrowableRow(3)
        sizer.AddGrowableRow(4)

        sizer.AddGrowableCol(0)
        sizer.AddGrowableCol(1)
        sizer.AddGrowableCol(2)

        self.panel.SetSizer(sizer)

        self.Center()  # Displays the window to the screen’s center
        self.Show()  # Shows the Frame

# Create Window
window = Window("WxPython GUI Application Demo")

# Execute the main GUI event loop
app.MainLoop()

Output

WxPython

Summary

In this article, we used wxPython to create a simple GUI application. wxPython toolkit can be used to create all sorts of GUI with numerous functionalities. The code itself is very simple and verbose. I hope this article helped to understand the key terms used in wxPython and also get an overview of structural hierarchy for the same.

Reference

wxPython: The GUI Toolkit for Python

Additional Reads

PySimpleGUI: An easy way to create GUIs in Python