Python has many libraries for GUI programming. Most of them are binding/wrapper to other popular GUI tool kits. PyGTK brings the power of GTK+ and GNOME to Python programmers, and the reverse is also true.
First importing ...
In most of the cases you only required to do the the first import, i.e., import gtk.
Here is a simple example, you can try it from python prompt.
What is GTK+ and PyGTK in particular ?
A good definition of GTK+ and related components are available at GTK Website.
GTK+ (GIMP Toolkit) is a C library for creating graphical user interfaces. It is licensed under the LGPL license, so you can develop "free/libre/open source" softwares, or even "proprietary/non-free" softwares using GTK+.
GTK is essentially an object oriented application programmers interface (API). Although written completely in C, it is implemented using the idea of classes and callback functions (pointers to functions).
PyGTK project's main aim is to provide a convenient wrapper for the GTK+ library for use in Python programs. As part of PyGTK project there are many sub-projects:
- pygobject -- The python bindings for GObject
- pygtk -- The bindings for pure GTK+
- gnome-python -- Bindings for GNOME core libraries
- gnome-python-desktop -- Bindings GNOME libraries part of the GNOME Desktop
- gnome-python-extras -- Bindings for GNOME libraries not part of the Developer or Desktop platforms
These wrappers provide all fruits of GNOME to Python programmers.
And about GNOME :
The GNOME project provides two things: The GNOME desktop environment, an intuitive and attractive desktop for end-users, users, and the GNOME development platform, an extensive framework for building applications that integrate into the rest of the desktop. You can read more about GNOME at GNOME Website
As a Python programmer, you know that Python provides a very good builtin library for daily programming tasks. PyGTK will be a very good choice for a complete desktop application development, let it be a simple utility, gnome applet, a common application or even an enterprise application.
Hmm... many choices, totally confused!
Yes, for a Python programmer there are many toolkits to choose from.
Now, why you should choose PyGTK instead of others?. Well, comparison with other toolkits is out of scope here, anyway you you can compare PyGTK with these toolkits: TkInter, WxPython, PyQt.
Now let's dive into an example
1 #!/usr/bin/env python 2 3 import gtk 4 5 def on_button_clicked(*args): 6 print "Hello World" 7 8 window = gtk.Window() 9 window.connect("delete_event", gtk.main_quit) 10 window.set_border_width(10) 11 button = gtk.Button("Hello World") 12 button.connect("clicked", on_button_clicked) 13 window.add(button) 14 window.show_all() 15 gtk.main()
In this example, first we are importing gtk, and you know what it means.
Then defining a function, this is called call-back function, because we are not calling this function directly, instead it is called by GTK+ when an event occurs. Example for events are 'clicked', 'focus_out_event', 'changed' etc. If you don't understand this paragraph, don't worry, go ahead.
Now we are creating an object of Window class. Then connecting an event to gtk.main_quit function. This 'delete_event' will occur when the user close the window.
Next we are creating a button object and connecting a function on 'clicked' event. And this button is added to window, then calling show_all method of Window object. And at last we are entering the gtk main loop by calling gtk.main() .
Glade/Gazpacho with PyGTK
The xml file created created with Glade/Gazpacho will be parsed using gtk.glade.XML() function, it will return an object, which can be used to get widgets in that glade file.
Here is a xml file created using glade:
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> <!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> <glade-interface> <widget class="GtkWindow" id="window1"> <property name="visible">True</property> <property name="title" translatable="yes">window1</property> <property name="type">GTK_WINDOW_TOPLEVEL</property> <property name="window_position">GTK_WIN_POS_NONE</property> <property name="modal">False</property> <property name="resizable">True</property> <property name="destroy_with_parent">False</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_NORMAL</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <child> <widget class="GtkButton" id="button1"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="label" translatable="yes">Hello World!</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> </widget> </child> </widget> </glade-interface>
To display the widgets in this xml, save it with .glade extension.
Here is a program to use this glade file (I assume, you saved it as project1.glade)
1 #!/usr/bin/env python 2 3 import gtk 4 import gtk.glade 5 6 def on_button_clicked(*args): 7 print "Hello World" 8 9 xml = gtk.glade.XML('project1.glade') 10 window = xml.get_widget('window1') 11 window.connect("delete_event", gtk.main_quit) 12 button = xml.get_widget('button1') 13 button.connect("clicked", on_button_clicked) 14 window.show_all() 15 gtk.main()
Events, signals and callbacks
GTK+ is an event driven toolkit, which means it will sleep in gtk.main() (a loop function) until an event occurs. Control is passed to the appropriate function when an event occurs on a particlular widget. Examples of events are clicked, toggled, delete_event etc. To explain this further, consider a dialog box with an 'OK' button, when user clicks on the button, GTK+ calls a function defined by the programmer.
This passing of control (or calling a function) is done using the idea of signals. When an event occurs, such as the press of a mouse button, the appropriate signal will be emitted by the widget that was pressed. This is how GTK+ does most of its useful work. There are signals that all widgets inherit, such as destroy, and there are signals that are widget specific, such as toggled on a toggle button.
To make click on a button perform an action, we set up a signal handler to catch these signals and call the appropriate function. This is done by using a gtk.Widget (from the GObject class) method such as:
handler_id = object.connect(name, func, func_data)
where object is the gtk.Widget instance which will be emitting the signal, and the first argument name is a string containing the name of the signal you wish to catch. The second argument, func, is the function you wish to be called when it is caught, and the third, func_data, the data you wish to pass to this function. The method returns a handler_id that can be used to disconnect or block the handler.
The function specified in the second argument is called a "callback function", and should generally be of the form:
def callback_func(widget, callback_data):
where the first argument will be a pointer to the widget that emitted the signal, and the second (callback_data) a pointer to the data given as the last argument to the connect() method as shown above.
If the callback function is an object method then it will have the general form:
def callback_meth(self, widget, callback_data):