Create and Use Source Code

The main purpose of wxGlade is to create code which will create the required windows.

In addition, empty handlers for the most common events can be generated.

The examples on this page are for Python, but the other supported languages will work similar.

Prerequisites and Code Generation

The options for code generation can be defined in the Properties window when the application object is selected in the Tree window:

For our example project from the previous page ‘Tutorial’ we want to generate:

  • Python code for wxWidgets 3.0 or Phoenix
  • all code in a single file
  • output file name Calculator.py
  • an application should be created, not just the window

So we select the root element “Application” in the Tree window and set the properties accordingly:

Application Properties

To actually create the source code, press the button Generate Source or hit Ctrl-G.

The generated source looks like this:

Generated Python Source Code

In this screenshot some parts were folded where the controls are created and placed in sizers. Especially for learning wxPython you may have a look at this code.

Application, Toplevel Windows

A wxGlade project may contain any number of toplevel Frames or Dialog.

In the application properties you need to select one frame or dialog as “Top window”.

wxGlade title wxGlade title

The toplevel window will be invoked from the generated application code:

class MyApp(wx.App):
    def OnInit(self):
        self.frame = CalculatorFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()

In the example code, you should be able to identify the uses of app, Myapp, frame and CalculatorFrame.

If Application->Name and Application->Class are deactivated, no application code will be generated. Usually you want to implement the application yourself, but still you can use the generated code as starting point.

The other, non-toplevel windows are usually called from your own code. Have a look at the generated code to see how to call them.

Be aware that you need to use different class names for your toplevel windows. wxGlade will display the class name with a yellow background if it’s not unique.

Code for Windows

This is the full code for our main window CalculatorFrame.

The code is separated into creation of controls, definition of properties and layout generation:

class CalculatorFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: CalculatorFrame.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.panel_1 = wx.Panel(self, wx.ID_ANY)
        self.text_value1 = wx.TextCtrl(self.panel_1, wx.ID_ANY, "")
        self.radiobox_operator = wx.RadioBox(self.panel_1, wx.ID_ANY, "",
            choices=["+", "-", "*", "/"], majorDimension=1, style=wx.RA_SPECIFY_ROWS)
        self.text_value2 = wx.TextCtrl(self.panel_1, wx.ID_ANY, "")
        self.text_result = wx.TextCtrl(self.panel_1, wx.ID_ANY, "",
            style=wx.TE_MULTILINE | wx.TE_READONLY)
        self.btn_execute = wx.Button(self.panel_1, wx.ID_ANY, "Execute")
        self.btn_reset = wx.Button(self.panel_1, wx.ID_ANY, "Reset")

        self.__set_properties()
        self.__do_layout()

        # end wxGlade

    def __set_properties(self):
        # begin wxGlade: CalculatorFrame.__set_properties
        self.SetTitle("Calculator")
        self.radiobox_operator.SetSelection(0)
        self.text_result.SetBackgroundColour(wx.Colour(212, 208, 200))
        self.btn_execute.SetDefault()
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: CalculatorFrame.__do_layout
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_2 = wx.BoxSizer(wx.VERTICAL)
        sizer_6 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_5 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_4 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_7 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
        label_1 = wx.StaticText(self.panel_1, wx.ID_ANY, "Value 1:")
        sizer_3.Add(label_1, 0, wx.ALIGN_CENTER_VERTICAL, 0)
        sizer_3.Add(self.text_value1, 1, 0, 0)
        sizer_2.Add(sizer_3, 0, wx.EXPAND, 0)
        label_4 = wx.StaticText(self.panel_1, wx.ID_ANY, "Operator:")
        sizer_7.Add(label_4, 0, wx.ALIGN_CENTER_VERTICAL, 0)
        sizer_7.Add(self.radiobox_operator, 0, 0, 0)
        sizer_2.Add(sizer_7, 0, wx.EXPAND, 0)
        label_2 = wx.StaticText(self.panel_1, wx.ID_ANY, "Value 2:")
        sizer_4.Add(label_2, 0, wx.ALIGN_CENTER_VERTICAL, 0)
        sizer_4.Add(self.text_value2, 1, 0, 0)
        sizer_2.Add(sizer_4, 0, wx.EXPAND, 0)
        static_line_1 = wx.StaticLine(self.panel_1, wx.ID_ANY)
        sizer_2.Add(static_line_1, 0, wx.BOTTOM | wx.EXPAND | wx.TOP, 5)
        label_3 = wx.StaticText(self.panel_1, wx.ID_ANY, "Result:")
        sizer_5.Add(label_3, 0, 0, 0)
        sizer_5.Add(self.text_result, 1, wx.EXPAND, 0)
        sizer_2.Add(sizer_5, 1, wx.EXPAND, 0)
        sizer_6.Add(self.btn_execute, 0, wx.ALL, 5)
        sizer_6.Add(self.btn_reset, 0, wx.ALL, 5)
        sizer_2.Add(sizer_6, 0, wx.ALIGN_CENTER, 0)
        self.panel_1.SetSizer(sizer_2)
        sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_1)
        self.Layout()
        self.SetSize((400, 300))
        # end wxGlade

When you run the Python file, the application is run and the frame created:

Screenshot

The code just creates the windows. There’s no functionality yet.

In the generated code you can see assignments like self.text_result = wx.TextCtrl(...). This allows you to access the control via the attribute result_text. You may e.g. call frame.text_result.SetValue(str(result)) to display a value in the Result text control.

Some widgets like StaticText are not accessible as attributes by default. You can change this by going to Properties->Widget and checking ‘Store as attribute’. For Sizers you can achieve the same on the “Common” tab.

As of now, nothing will happen if the user hits the “Execute” button. So we need an event handler for this.

Code for Event Handlers

Traditional programs or scripts usually have a defined flow.

GUI programs on the other hand, are event-driven and the flow depends on the user’s actions. The events like mouse clicks are delivered from the operating system or window manager to the application. The receiving side is an infinite loop, called “event loop” or “main loop”. When you have a look at the last lines of a Python file that wxGlade wrote, you will see that the MainLoop method of your application is called. The main loop receives events from e.g. the Windows operating sytem and dispatches it to windows and controls. To handle things like mouse clicks, menu selections, button clicks etc. you need to register handlers.

wxGlade allows you to enter handler names. For any of these names, empty method stubs will be generated in the source code file and the methods will be bound when the window is created. Alternatively, you may define and register handlers yourself.

Example: button event EVT_BUTTON

The main event of a button is EVT_BUTTON. In the following example we want to call a method on_execute_button_clicked whenever the “Execute” button is clicked.

Method 1: use wxGlade

In the Properties window you can see the events (most controls have more than just one event) and enter the handler name:

EVT_BUTTON Event Handler

The generated code will look like this:

def __init__(self, *args, **kwds):
    ...
    self.execute_button = wx.Button(self.notebook_1_pane_1, wx.ID_ANY, "Execute")
    ...
    self.Bind(wx.EVT_BUTTON, self.on_button_clicked, self.execute_button)

def on_execute_button_clicked(self, event):  # wxGlade: MyFrame.<event_handler>
    print("Event handler 'on_execute_button_clicked' not implemented!")
    event.Skip()

The default handler just prints a message to the console and calls event.Skip() to forward the event to the the parent of the button.

Method 2: register event handler

Alternatively, you can also register an event handler yourself, using code like this:

self.execute_button.Bind(wx.EVT_BUTTON, self.on_execute_button_clicked)

wxGlade will only help you with the most important events, e.g. for the button it will just offer to generate a handler for EVT_BUTTON. You may want to register and handle other events like mouse movements as well.

User Code: Implement Functionality

There are two ways to implement functionality for your application:
  • Directly edit the code file()s) written by wxGlade.
  • Import the generated module(s) and override class and event handler in your own code files.

For anything else than simple glue code, the latter is the recommended approach.

Example 1: Edit in place / “Keep user code”

If you want to use the first approach, you need to set “Keep user code” for the application in the Properties window:

Option: Keep User Code

In this case, when you hit the Generate Source button, wxGlade will read the file and only overwrite the sections that were marked with # begin wxGlade:... and # end wxGlade.

Please be aware that this is not too robust when you e.g. rename objects. Always keep backups!

Event handlers are marked with # wxGlade: MyFrame.<event_handler>. They will be read and written back unchanged. Don’t modify the marker.

To implement functionality, replace the default handler, e.g.:

def on_execute_button_clicked(self, event):  # wxGlade: MyFrame.<event_handler>
    print("Event handler 'on_execute_button_clicked' not implemented!")
    event.Skip()

with your own code like this (of course you should add also validation and error reporting):

def on_execute_button_clicked(self, event):  # wxGlade: MyFrame.<event_handler>
    value1 = float( self.text_value1.GetValue() )
    value2 = float( self.text_value2.GetValue() )
    operator = self.radiobox_operator.GetSelection() # a number from 0 to 3
    if operator==0:    result = value1 + value2
    elif operator==1:  result = value1 - value2
    elif operator==2:  result = value1 * value2
    elif operator==3:  result = value1 / value2
    self.text_result.AppendText("%s\n"%result)
    event.Skip()

The result:

Option: Keep User Code
The files can be found in the folder wxglade/examples/Calculator:
In these files, the event handlers for the two buttons are defined in Properties -> Events -> EVT_BUTTON:
  • on_execute_button_clicked
  • on_reset_button_clicked

Please be aware that this example code is far far away from any good coding style. Please do better in your own code!

It would be good practice to:
  • separate the business logic from the user interface by implementing e.g. methods like
    validate_value(value), calculate(value1, operator, value2)
  • validate the contents of text_value1/2 on every change of content (EVT_TEXT)
  • report failed validation by colorizing the controls
  • catch and log exceptions like ZeroDivisionError

Example 2: Import and override

To actually use the generated event handler code and extend it with the required functionality, it’s best to create another Python file, import the generated code and use app/MyApp as template.

For example, set wxGlade output file name to Calculator_GUI.py and let it generate the GUI code. Now create a file Calculator_Main.py:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import wx
import gettext
from Calculator_GUI import CalculatorFrame


class MyFrame(CalculatorFrame):
    def __init__(self, *args, **kwds):
        CalculatorFrame.__init__(self, *args, **kwds)
        # if required, insert more initialization code here and create data structures

    def on_execute_button_clicked(self, event):
        # XXX add validation and error reporting!
        value1 = float( self.text_value1.GetValue() )
        value2 = float( self.text_value2.GetValue() )
        operator = self.radiobox_operator.GetSelection() # a number from 0 to 3
        if operator==0:    result = value1 + value2
        elif operator==1:  result = value1 - value2
        elif operator==2:  result = value1 * value2
        elif operator==3:  result = value1 / value2
        self.text_result.AppendText("%s\n"%result)
        event.Skip()

    def on_reset_button_clicked(self, event):
        self.text_result.Clear()
        event.Skip()


class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True


if __name__ == "__main__":
    gettext.install("app") # replace with the appropriate catalog name
    app = MyApp(0)
    app.MainLoop()
The files can be found in the folder wxglade/examples/Calculator:

Additionally, these files demonstrate a menu bar which will be explained in the next section Menu, Status Bar, Tool Bar.

Hints and Tips

Note

Implementing event handlers is easiest if you use an IDE with a debugger, like Wing IDE Professional.
Just set a breakpoint at the event handler and the introspection features and code completion will save you a lot of time:

Debug Probe

Note

During development, you should always run your program from or within a console window.
This way you will see if there are any exceptions being reported at stderr:

Windows console window with exception