2.4 GladeView

Once you have written three (two?) applications using the PyGTK classes and commands directly, you get very bored of hand-coding the widgets and their structure. Sure, you have total control over them, and you can build them programatically, which is why you might want to do it for small parts of your application, but for anything that is medium to large-scale, having to maintain all that code makes changing the UI very painful. Damon Chaplin's application Glade provides a way to create a GTK+ interface visually, and it is normally used to generate C or C++ code that creates the widgets. It also saves the interface specification in an XML file. Knowing this, James Henstridge, the author of PyGTK, wrote libglade, a killer library (this was years ago, but I digress) that renders widgets based on specifications in an XML file. libglade allows you to keep the interface definition separate from the code, which is an awesome idea, since it drastically reduces the amount of interface code (and the consequent burden of maintaining it). Being able to use Glade to revisit and tweak your interface without having to regenerate code is also a huge advantage.

Anyway, Kiwi lets you use Glade interfaces in a very convenient manner, by using the GladeView class. Let's show this off by redoing the last example using glade. First thing would be running Glade and creating a window and putting a label into it. Name the window hey and turn the visible property off (using the Common tab of the Properties dialog). Save the file (careful with that Save dialog, it creates directories and is generally evil in my opinion) as hey.glade. And then code up heyglade.py (all this is available in examples/HeyPlanet/):


/mondo/src/PYTHON/python2.4-2.4.1/Doc/texinputs/../examples/HeyPlanet/heyglade.py

Oops. Where did all that code go? Right, we are now using the glade file to generate the UI. So we didn't even need to subclass GladeView; we just passed in a parameter that told it what glade file to use, and the same delete handler. Note also that we used show_and_loop() instead of show_all_and_loop()3.

The gladefile parameter indicates the file it should open. If the name you pass in doesn't have a .glade suffix, GladeView will append it and try to open it; in our cases, it will try to open the file hey.glade. However, this argument does a bit more than just specifying the file (when using this form of the constructor, which is simplified): it also specifies by default the name of the toplevel widget in the glade file. This is why I specifically stated the window should be named hey two paragraphs back. That widget is attached to the view instance with the name toplevel.

If you want to use another specific toplevel widget name, just use the extra constructor parameter toplevel_name. This can be useful if you have many windows in the same Glade file; you can reuse the glade file by just defining multiple GladeView instances (or subclass instances) with the same gladefile but specifying different toplevel widgets as each individual toplevel_name.

There are some common mistakes to be made when using the GladeView, and Kiwi raises special exceptions for three them.

  1. The first one is forgetting to specify the gladefile, or giving it the wrong name. Kiwi will try to look for the file in its glade search path (which can be set by the GLADEPATH variable and also by using Kiwi.Views.set_gladepath()), and if it doesn't find it, it will complain with an IOError and stop.
  2. The second is not having a widget with the name of the gladefile in your glade interface. This is only a mistake if you don't specify toplevel_name, of course. Kiwi raises an AttributeError here.
  3. The third mistake is forgetting to make the window hidden. We want the window to be hidden to allow you to control when exactly it is shown, and if you use the same glade file for all your dialogs, you quickly will understand why. Kiwi prints a warning for this, as I don't consider it a fatal error.

To use GladeView effectively, it's important to define the widgets list, which defines what widgets are to be attached to your class. This list has its own semantics, which I discuss in the next section.



Footnotes

...show_all_and_loop()3
It is important to note that GladeView does *not* allow you to call show_all_and_loop() -- you must use show_and_loop() instead. There is a reason for this. show_all means that all widgets under the toplevel widget should be shown; however in glade, since most widgets are visible by default, you only need to turn off visibility on the toplevel window to get the default hidden effect. This alone would not be a problem, but the fact is that certain widgets can be configured in glade to *require* being hidden (either because you want them initially hidden, or because they do something special, like the GtkToolbar: if you choose to use `Only Text' or `Only Icons', glade implements this by hiding the icons or text, respectively). This would break with show_all and too many bug reports told me it was enough reason to turn it off. You can of course call it manually on the window if you are really determined do so.