Easy GUI applications with Python, GTK+ and Glade

Foreword

This tutorial is not intended to be a detailed guide on using Glade or programming in Python, but rather an introduction to using GTK+/Glade in conjunction with Python to create elegant, maintainable GUI applications for the Gnome desktop.

This guide assumes the capability to hunt down and install packages on your distribution of choice as well as some degree of development experience in Python.

If you want to create GUI driven applications, it’s in your best interest to use an interface builder. For GTK, the best such tool is Glade. Glade is a WYSIWYG interface builder which generates XML files describing the user interface and callbacks for your application. This allows you to completely separate your view (user interface) from the rest of your code and focus on the underlying logic of your program rather than needlessly adjusting the padding of a widget for hours. In most cases, you won’t have to write user interface drawing code at all.

Let’s get started.

Prerequisites

  • Python (2.4 or higher recommended)
  • Python Glade library (python-glade2)
  • Glade interface builder, Glade3 recommended (glade-3)

Building the user interface

Open the Glade interface builder and familiarize yourself with the interface. The ‘Palette’ contains all of your toolbox options, analogous to brush tools in GIMP. The ‘Properties’ panel is your one stop shop for adjusting metadata about your widgets such as display options (‘General’, ‘Common’) and callbacks (‘Signals’). Finally, the main panel is the canvas on which you will be drawing your application GUI.

For this example, we’ll be creating a window with a single button that says “Hello, world!” Pay special attention to the ‘Name’ properties of each widget, as we will be referencing them from the Python code, and they must correlate.

Step one: In the Palette, click the ‘Window’ icon under ‘Top Levels’. It’s the one that looks like a blank window, but you can also mouse over each icon to see its description.

Palette window

This will add a checkered box to your canvas.

Canvas - Window

Step two: In the properties window, set the ‘Window Title’ to what should appear in the title bar (in this case, we’ll use “Hello, world!”) and change the ‘Name’ to ‘main_window’

Properties window

Step three: Switch to the ‘Signals’ tab in the Properties window and set up a handler for the ‘destroy’ signal of the main window. Set the handler to ‘on_main_window_destroy’. This signal will fire when the user closes the application window.

Main window signals

Step four: Back in the Palette, click the ‘Button’ icon under ‘Control and Display’ and then click anywhere in the gray checkered window we created a moment ago. In properties, change the Label to ‘Hello, world!’ and the Name to ‘hello_button’

Canvas
Button properties

Step five: Add a handler for the ‘clicked’ signal of the hello button. Name the callback ‘on_hello_button_clicked’. This signal will fire whenever the user clicks on the button.

Button signals

Now just save the project as ‘gtk_hello_world.glade’ and exit the application. Congratulations, you’ve successfully built a GUI for your application. Give yourself a pat on the back.

Writing the code

The code is rather simple, we don’t have to mess with any specifics about drawing the widgets, we just tell them when to display and what to do when different events are called. If you don’t understand how classes in Python work, go read up on them before continuing.

import gtk
import gtk.glade


GLADE_FILE = 'gtk_hello_world.glade'


# A decorator that defines a function as a callback to a Glade signal
def glade_callback(function):
    function.__glade_callback__ = True
    return function

# Retrieves a dictionary of functions decorated as Glade callbacks
def get_glade_callbacks(input):
    attributes = dir(input)

    result = {}
    for key in attributes:
        attr = getattr(input, key)
        if callable(attr) and hasattr(attr, '__glade_callback__'):
            result[key] = attr

    return result


class HelloWorld(object):
    def run(self):
        self.interface = gtk.glade.XML(GLADE_FILE)

        self.callbacks = get_glade_callbacks(self)
        self.interface.signal_autoconnect(self.callbacks)

        self.main_window = self.interface.get_widget('main_window')
        self.main_window.show()

        gtk.main()


    @glade_callback
    def on_hello_button_clicked(self, data):
        print 'Hello, world!'

    @glade_callback
    def on_main_window_destroy(self, data):
        print 'Main window destroyed, exiting...'
        gtk.main_quit()


if __name__ == "__main__":
    hello = HelloWorld()
    hello.run()

The glade_callback function is a decorator which sets an attribute on a function defining it as a Glade callback. The get_glade_callbacks function looks for all functions with that attribute and returns them as a dictionary. I use these two helper functions in all of my GTK applications.

The run method is where the meat of the action happens. First we tell Glade to load the GUI that we created earlier in the tutorial:

    self.interface = gtk.glade.XML(GLADE_FILE)

Then we connect all of our Glade callbacks (all functions decorated with glade_callback) to their respective Glade signals as we defined them in the interface builder using introspection.

    self.callbacks = get_glade_callbacks(self)
    self.interface.signal_autoconnect(self.callbacks)

Now we get a handle on the main window and tell it to display. The name comes directly from the ‘Name’ property we set in Glade.

    self.main_window = self.interface.get_widget('main_window')
    self.main_window.show()

Finally, we tell GTK to start handling events for the program and passing them off to our custom signal handlers.

    gtk.main()

That little bit of scaffolding takes care of all of the GUI aspects of the application, and we’re now free to just worry about what we do when a user performs a specific action. That’s where our callbacks come in, which are the two functions on_hello_button_clicked which is called whenever the user clicks our button and on_main_window_destroy which is called when the window is closed.

You can grab the full source code and Glade file here.

Further reading material

Hopefully this guide was helpful. Comments or suggestions welcome.

Happy hacking!