23 Sep

I have just learned a few more tricks on how to best work with GTK and Python. First, let me start at the beginning. After you create a Glade file (If you don't know what Glade is, read this), the next step is to create the Python code to load the Glade file (i.e. turn the XML into actual widgets on the screen), and hook up all the signals to actual Python methods. Well, if you're like me, you don't know how many parameters are needed for each signal handler, and soon you find yourself looking for examples (or just guessing) on how to hook up various signals (such as a button click, treeview drag_begin, window destroy, etc...). This can become a very time consuming and frustrating process, especially when you are just learning Python & GTK.

Trick #1: Using Synaptic Package Manager (or equivalent), go get the tepache package. This package gives you a command line way of generating the Python code needed to load a Glade file into a class, auto-connect all the signals, and it even stubs out all the signal handler methods. If that wasn't enough, it even helps setup language translations for your Glade file.

To use the tepache command, use the following syntax in the terminal window: tepache YourFile.Glade

After you run this command, it will generate a .py file, named YourFile.py. Here is the output from the tepache command using one of my more complex Glade files:

import os
import gtk
import gnome

from SimpleGladeApp import SimpleGladeApp
from SimpleGladeApp import bindtextdomain

app_name = "main"
app_version = "0.0.1"

glade_dir = ""
locale_dir = ""

bindtextdomain(app_name, locale_dir)


class App1(SimpleGladeApp):

def __init__(self, path="Main.glade",
root="app1",
domain=app_name, **kwargs):
path = os.path.join(glade_dir, path)
SimpleGladeApp.__init__(self, path, root, domain, **kwargs)

def new(self):
print "A new %s has been created" % self.__class__.__name__


def on_app1_destroy(self, widget, *args):
print "on_app1_destroy called with self.%s" % widget.get_name()
gtk.main_quit()


def on_mnuQuit_activate(self, widget, *args):
print "on_mnuQuit_activate called with self.%s" % widget.get_name()


def on_mnuAbout_activate(self, widget, *args):
print "on_mnuAbout_activate called with self.%s" % widget.get_name()


def on_treeFiles_drag_drop(self, widget, *args):
print "on_treeFiles_drag_drop called with self.%s" % widget.get_name()


def on_tlbAddTrack_clicked(self, widget, *args):
print "on_tlbAddTrack_clicked called with self.%s" % widget.get_name()


def on_tlbRemoveTrack_clicked(self, widget, *args):
print "on_tlbRemoveTrack_clicked called with self.%s" % widget.get_name()


def on_hscrollbar1_value_changed(self, widget, *args):
print "on_hscrollbar1_value_changed called with self.%s" % widget.get_name()


def on_vscrollbar1_value_changed(self, widget, *args):
print "on_vscrollbar1_value_changed called with self.%s" % widget.get_name()


def on_scrolledwindow_Right_drag_drop(self, widget, *args):
print "on_scrolledwindow_Right_drag_drop called with self.%s" % widget.get_name()


def main():
gnome.program_init("main", "0.0.1")
app1 = App1()

app1.run()

if __name__ == "__main__":
main()

Trick #2: There is a library that comes with pyGtk called SimpleGladeApp, which is going to save you a ton of time. It is used quite heavily in the tepache output (as you can see from my example). What does this library do, you ask?

Let me break it down for you:
  1. It loads a Glade XML file and returns an object for your form. It reminds me very much of a form object from the Windows world (i.e. Visual Basic.NET, C# Windows Application, etc...).
  2. On this new form object, it has a reference to every single widget on your form. For example: self.myTree, self.btnToolBar1, self.Canvas1.
  3. It adds a show() and hide() method for every widget.
  4. It adds a grab_focus() method for every widget.
  5. It adds a run() and quit() for your form (which simply calls the main_loop() gtk methods.
  6. It auto-connects all the signal handlers you have defined (of that tepache defined) to the signals defined in the Glade file.
  7. It translates all the text in the Glade file (if you have the appropriate translation files in your project).
So, now that you know this, take a look at my example above again. Anywhere in this class you can access all the widgets, hide and show them, set focus to them, all without calling the GladeFile.get_widget("") method.

I hope this blog entry is helpful to some of you. It's going to save me a ton of time trying to setup my GUI and hook up all the signals. Good luck!