PYGTK: New-Style Python Class Using Builder

I have searched Google and the web for a resource on creating Python new-style classes for windows and dialogs when using GTK’s Builder and Glade UI files. I haven’t found much, but have managed to piece together a workable model. The basics of the process is to create a new class that inherits from gtk.Window or gtk.Dialog. Override the __new__() method and retrieve the window object from builder, call a method to act like an __init__() method, and return the new window object.

The Window Class

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

import gtk, sys, os

class MainWindow(gtk.Window):
    __gtype_name__ = "MainWindow"

    def __new__(cls):
        """This method creates and binds the builder window to class.

        In order for this to work correctly, the class of the main
        window in the Glade UI file must be the same as the name of
        this class."""
        app_path = os.path.dirname(__file__)
        try:
            builder = gtk.Builder()
            builder.add_from_file(os.path.join(app_path, "main.ui"))
        except:
            print "Failed to load XML GUI file main.ui"
            sys.exit(1)
        new_object = builder.get_object('window')
        new_object.finish_initializing(builder)
        return new_object

    def finish_initializing(self, builder):
        """Treat this as the __init__() method.

        Arguments pass in must be passed from __new__()."""
        builder.connect_signals(self)

        # Add any other initialization here

Notice that our MainWindow class inherits from gtk.Window. The __gtype_name__ variable creates a type name that is the same as our class. The __new__() method is passed the class inherited. The try/except block creates a Builder object and loads the Glade file. We create new_object and assign it to Builder’s window object. You will want to replace window with the name of your window object used when creating the window in Glade. We then call the new_object’s finish_initializing method, pass it the Builder object we created. You can treat this method as a stand in for an __init__() of the class. If you have objects you need to pass to the class, you will first pass them to __new__() and __new__() can pass them on to finish_initializing(). Once finish_initializing() returns, __new__() returns new_object.

The only thing that finish_initializing() has to do is call Builder’s connect_signals(). However, you will probably want to finish up any other initialization you need for the window, like getting objects you need to interact with from Builder, initializing class objects, etc.

The Glade File

In order for all this to work, we need to edit the Glade UI file and make one small change. In order for new_object to call finish_initializing(), the class type it gets from Builder’s get_object() method must be the same as our class name. Open the Glade file for editing and change the window’s class from GtkWindow or GtkDialog to the created class name.

Displaying the Window

The rest is just creating an instance of the class, calling show(), and gtk.main().

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

import sys, gtk
import MainWindow

if __name__ == "__main__":
    app = MainWindow.MainWindow()
    app.show()
    gtk.main()

That’s all there is to it. You now have a GTK Window class that you can create using the new-style Python classes. The advantage to this method is you do not have to reference the class and then the window object, because the class is a GTK Window.

Advertisements

6 comments on “PYGTK: New-Style Python Class Using Builder

  1. alex says:

    That’s pretty helpful. Thanks for that.
    One small question though…
    When you suggest we change the name of our class in the glade file… How are you actually supposed to do that ? I found no option in glade, and when replacing the object’s class attribute manually in the xml, the builder chokes on it (and the file can also no longer be opened by glade…). I saw people mentioning catalogs (http://askubuntu.com/questions/86466/custom-pygtk-dialog-with-glade)… is that what I want to do ? (That would make the whole approach a bit less sexy but still probably worth it)
    Thank you again 🙂

  2. alex says:

    oops sorry for double comment, didn’t realize I had posted already ! feel free to get rid of the first one !

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s