(Assume the purpose of the application is already known)
Of course, building an application is much more complicated than assuming you have an idea and then adding the four points on this slide. But these are the areas that are most relevant from a desktop point of view. What your application actually does is usually independent of the toolkit you use to build it. But how you implement the external face of your application is our concern in this talk.
w.connect(name, handler,
data)def handler(widget, data): ...The last point just emphasises the fact that we can use just about anything that is "callable" when we are creating a callback, so the developer can feel free to use classes as much or as little as they like.
When connecting handlers to signals, as many "data" arguments as you like can be passed in. So w.connect(name, handler, foo, bar, baz) is perfectly fine. The handler obviously has to accept the right number of parameters, too. This extra data (and no data is required, by the way) is useful to provide some context in the callback so that callback functions can be shared between multiple signals.
Because the widget raising the signal is passed into each handler, we can easily share handlers between widgets. It is very common to have a single function for hiding dialog boxes when they are closed (rather than destroying the widget), for example.
The "generally" qualification on the signal handler prototype is because
some handlers take extra paramters all the time. For example, the 'response'
signal on a GtkDialog box will always have a response identifier
as the second argument (before the user data). The only way to be certain about
a specific prototype is to look at the reference documentation.
def handler(widget, event, data): ... event parameter is a GdkEvent instance.
event.typegtk.gdk.BUTTON_PRESS and
gtk.gdk.SCOLLevent depend upon the typeBecause event handlers receive so much context in the call (the widget and the event), you could right a single "mother of all event handlers" that does everything. But try to resist — your code will not be very maintainable.
However, a certain amount of collapsing of common functionality is helped by this type of handler signature. For example, you could decide to handlie all occurrences of keypresses (outside of entry widgets) in a single place.
w.set_events() and w.add_events() to
control the event maskgtk.Label,
gtk.MenuItem)
EventBox widgetw.emit_stop_by_name(signalName)GtkDialog class. Manual tells us:


This is a simulation of a "back of the envelope" design and how I picture the application's windows being arranged. The main window is displayed at startup, the other three are brought up under the control of Main as required.
The initial appearance of Glade, before loading of starting any project.
A closer view of the widget palette, showing the widgets that are only available in a "GNOME" (as opposed to "GTK") project. The top-left widget is the main GNOME application window (menubar, toolbar, status bar, progress bar and main application area).
A detail view of the "GNOME Application Window" widget.
Here we can see how the AboutBox being created on the right can
have various attributes set through the Glade Properties box on the
left.
<widget class="GnomeAbout" id="about">
<property name="border_width">5</property>
<property name="destroy_with_parent">False</property>
<property name="icon">silly-icon.png</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="logo">silly-icon.png</property>
...
<property name="authors">
Malcolm Tredinnick <malcolm@commsecure.com.au>
</property>
<property name="translator_credits" translatable="yes">
translator_credits</property>
</widget>
This is an extract of the XML output from the earlier screenshots. Only the about box description is shown here. The point is that the save format of Glade is easily readable by humans and machine readable for any XML-capable tools.
A typical Glade editing session can result in a lot of windows being open at once. This can be a nuisance on smaller (e.g. laptop) screens.
import pygtk
pygtk.require('2.0')
import gtk.glade, gnome, gnome.ui, bonobo
...
def main(name, version):
gnome.init(name, version)
...
# Create the application, load the glade file,
# call bonobo.main() to start, bonobo.main_quit()
# to end.
The pygtk.require('2.0') line is so that a system with parallel
installs of gtk-1.2 and gtk-2 uses the correct version of pygtk.
Failure to import gnome.ui will result in no stock icons
displaying in menu items or the toolbar.
class About:
def __init__(self, gladeFile, name, version):
tree = gtk.glade.XML(gladeFile)
self.aboutBox = tree.get_widget('about')
self.aboutBox.set_property('name', name)
self.aboutBox.set_property('version', version)
# Hook up individual signals and events.
self.aboutBox.connect('response', dialogResponse)
self.aboutBox.connect('close', dialogClose)
self.aboutBox.connect('delete_event', dialogClose)
def show(self, *args):
self.aboutBox.show()
def dialogClose(dialog):
self.dialog.hide()
return True
def dialogResponse(dialog, response, *args):
if response < 0:
dialog.hide()
dialog.emit_stop_by_name('response')
# The 'windows' parameter to __init__ is a mapping of top-level window
# names to their widgets.
class Main:
def __init__(self, gladeFile, windows):
tree = gtk.glade.XML(gladeFile, 'main')
main = tree.get_widget('main')
# Quit the program when the main window is closed.
main.connect('delete_event', self.quit)
# Callbacks for all the menu items.
callbacks = {
'on_quit_activate': self.quit,
'on_about_activate': windows['about'].show,
}
tree.signal_autoconnect(callbacks)
Through judicious use of the signal_autoconnect() method,
hooking up multiple callbacks is easy. The "judicious" portion here is because
we only constructed the XMl tree from the 'main' widget downwards — not
for the entire file. This prevents the autoconnection from running wild amongst
handlers we do not want to connect in this class.
gnome.init()
call to read
appProperties = {'app-datadir': _currentDir()}
gnome.init(name, version, properties = appProperties)
gnome/help/<LANG>/ under this
prefix.
def showHelp(self, *args):
gnome.help_display('debugger-help.xml')
import gettext, locale
...
def main(name, version):
gettextName = 'debuggerDemo'
localeDir = '%s/locale' % _currentDir()
gettext.bindtextdomain(gettextName, localeDir)
gettext.textdomain(gettextName)
gettext.install(gettextName, localeDir, unicode = 1)
touch po/POTFILES.inintltool-update -mintltool-update -p -g debuggerDemointltool-update will be run to update existing
PO files.[Desktop Entry] Encoding=UTF-8 _Name=Project Management _Comment=Planner Project Management Exec=planner %F Icon=gnome-planner.png Terminal=false Type=Application Categories=Application;Office;ProjectManagement; StartupNotify=true MimeType=application/x-planner;
gtk-demo.py that comes with the pygtk2 distribution.
Shows what is possible in GTK