PyGTK For GUI Programming/First Steps

< PyGTK For GUI Programming

This chapter aims to familiarize the reader with the basic classes and functions of the PyGTK module, and how to link them together. To start off, open an interactive Python shell (i.e. launch IDLE, or type `python` on the command line of a terminal), and enter the following (case matters):

1 import gtk
2 
3 window = gtk.Window()
4 label = gtk.Label("Hello, world!")
5 
6 window.add(label)
7 
8 window.show_all()

If you enter the above code into a file and execute that file (by invoking the interpreter with the file as an argument or indirectly through some other IDE's) then it could happen that nothing seems to happen at all. This is because after the window.show_all() call the interpreter (and thus also the PyGTK application) is terminating. In order for this example to work in this context it is sufficient to append gtk.main(), see the Signals and Callbacks section for more detail.

A bug in some versions of PyGTK causes IDLE to crash when using the `gtk` module. If you launch IDLE, start entering the lines above, and suddenly the IDLE window closes or disappears - usually when you hit [Enter] at the end of one of the lines - then you've been bitten by the bug! Open a command shell/terminal, type the "python" command, hit [Enter], and start the above script again.
Technical Note:

This snippet of code creates a window with the text "Hello, world!" inside (see screenshot).

GTK Objects and Containers

In the example code above, the gtk.Window() object self-evidently represents the GUI window, and the widget gtk.Label is added to the object with the add() method. The add method, however, only allows a single object to be added to the window. Since you often want to put multiple widgets into a window, some sort of container object, such as gtk.VBox, needs to be added instead. The gtk.VBox object can contain and organize multiple widgets into a Vertical column. Similarly, the gtk.HBox object is also available, organizing its child widgets into a Horizontal row. To create more sophisticated layouts, you can nest the container objects, i.e. have a gtk.HBox inside a gtk.VBox.

The use of these objects is demonstrated in the illustration on the right. The gtk.WindowGroup object is optional, but allows your application to display more than one gtk.Window. The chapter 'Multiple Windows' explains how to use this; for now, we will stick to a single window.


Here is an example of a simple PyGTK programme which utilizes the gtk.VBox and gtk.HBox objects to put multiple widgets on the screen - try typing this into the interactive Python or IDLE interpreter:

 1 import gtk
 2 
 3 window = gtk.Window()
 4 entry = gtk.Entry()
 5 button_ok = gtk.Button("OK")
 6 button_cancel = gtk.Button("Cancel")
 7 
 8 vbox = gtk.VBox()
 9 vbox.pack_start(entry)
10 hbox = gtk.HBox()
11 hbox.pack_start(button_ok)
12 hbox.pack_start(button_cancel)
13 vbox.pack_start(hbox)
14 
15 window.add(vbox)
16 window.show_all()

The result of the code above should be a window with an input box and two buttons:

Signals and Callbacks

In order to get your application to react to the GUI, you can tap into events which occur on widgets and tell PyGTK to run a function (known as a callback function) when that event happens. For example, when the user clicks on a button, the "clicked" event for that specific widget is emitted, and if you have connected it to a callback function that function is run.

To connect an event with a function, call the .connect() method on the widget that will emit the event. The syntax of this method is:

handler_id = widget.connect(event_name, callback_function[, function_data])

The return value to .connect() can be captured so the connection can be revoked.

The callback function should be in the form:

def callback_function(widget, callback_data=None)

The name of the function and its arguments can be called anything.

Finally, to make sure your events are dealt with, add the following code to the end of the application:

gtk.main()

The gtk.main() function listens for events and runs any callback functions that have been connected to them. This function stays running until the window is closed by the operating system's window manager, or gtk.main_quit() is run.

Below is a modified version of the sample code above, with a some callback functions defined and connected to button events.

 1 import gtk
 2 
 3 # Define the callback functions first:
 4 def exit(widget, callback_data=None):
 5   window.hide_all()
 6   gtk.main_quit()
 7 
 8 window = gtk.Window()
 9 entry = gtk.Entry()
10 button_ok = gtk.Button("OK")
11 button_cancel = gtk.Button("Cancel")
12 
13 # Connect events to callback functions:
14 button_cancel.connect("clicked", exit)
15 
16 vbox = gtk.VBox()
17 vbox.pack_start(entry)
18 hbox = gtk.HBox()
19 hbox.pack_start(button_ok)
20 hbox.pack_start(button_cancel)
21 vbox.pack_start(hbox)
22 
23 window.add(vbox)
24 window.show_all()
25 # Put gtk.main() last so our callback functions are used.
26 gtk.main()

Putting It All Together

The following code uses all of the methods discussed above to create a very simple GTK application that asks for your name and prints it to the console. Copy and save the following text in a file and run python example.py on the command line (replacing example.py with the name of the file you just created).

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 
 4 import pygtk
 5 pygtk.require('2.0')
 6 
 7 import gtk
 8 
 9 
10 class Application():
11     
12     def __init__(self):
13         self.window = gtk.Window()
14         self.window.set_title("Example GTK Application")
15         
16         self.create_widgets()
17         self.connect_signals()
18         
19         self.window.show_all()
20         gtk.main()
21     
22     
23     def create_widgets(self):
24         self.vbox = gtk.VBox(spacing=10)
25         
26         self.hbox_1 = gtk.HBox(spacing=10)
27         self.label = gtk.Label("Your Name:")
28         self.hbox_1.pack_start(self.label)
29         self.entry = gtk.Entry()
30         self.hbox_1.pack_start(self.entry)
31         
32         self.hbox_2 = gtk.HBox(spacing=10)
33         self.button_ok = gtk.Button("OK")
34         self.hbox_2.pack_start(self.button_ok)
35         self.button_exit = gtk.Button("Exit")
36         self.hbox_2.pack_start(self.button_exit)
37         
38         self.vbox.pack_start(self.hbox_1)
39         self.vbox.pack_start(self.hbox_2)
40         
41         self.window.add(self.vbox)
42     
43     
44     def connect_signals(self):
45         self.button_ok.connect("clicked", self.callback_ok)
46         self.button_exit.connect("clicked", self.callback_exit)
47     
48     
49     def callback_ok(self, widget, callback_data=None):
50         name = self.entry.get_text()
51         print name
52     
53     
54     def callback_exit(self, widget, callback_data=None):
55         gtk.main_quit()
56     
57 
58 if __name__ == "__main__":
59     app = Application()

This application is structured inside a single class, Application. This approach allows the names of the GTK widgets and other objects to reside in their own namespace, and also makes it possible to import the file in other scripts and let the programmer decide when to create and display the GUI.

This article is issued from Wikibooks. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.