September 1, 2014
 
 
RSSRSS feed

Graphical Python Programming With PyGTK

Making a Push Button

  • May 14, 2009
  • By Akkana Peck

Whitespaces and formatting are meaningful in Python, so the code is posted both inline in this article, and on a separate page which is linked at the bottom.

Past Linux Planet articles have described programming in Python with TkInter But you have several other choices for graphical programs in Python. One of the most powerful is Python-GTK, or PyGTK.

Python-GTK is a set of Python bindings for the common GTK+ library seen in many Linux applications such as GIMP and Inkscape. You can easily write python programs that bring up windows using the same graphical controls that you're used to seeing in other programs.

A very simple PyGTK program to show a single push button looks something like this, with comments to explain what each line does:

#!/usr/bin/env python

import gtk

# This function will be called whenever you click on your button:
def click_handler(widget) :
# quit the application:
gtk.main_quit()

# Create the main window:
win = gtk.Window()

# Organize widgets in a vertical box:
vbox = gtk.VBox()
win.add(vbox)

# Make a pushbutton:
button = gtk.Button("Push me!")

# When it's clicked, call our handler:
button.connect("clicked", click_handler)

# Add it to the window:
vbox.pack_start(button)
button.show()

# Obey the window manager quit signal:
win.connect("destroy", gtk.main_quit)

vbox.show()
win.show()
gtk.main()

One line needs more explanation: win.connect("destroy", gtk.main_quit). This addresses that "X" you see at the far right of every window's titlebar. You want your application to quit when you click that -- but for some reason, GTK applications don't unless you explicitly tell them to. Without that line, when you click on the "X" your window will disappear but the python script will just go on running. So it's always a good idea to handle the "destroy" signal in your PyGTK programs.

Run the script, and it brings up a tiny window like you see in Figure 1.

 

Not bad! And PyGTK has lots more widgets you can use: it has the usual complement of labels, sliders, toggle buttons, scrollbars and so forth. But this article is about how to draw graphics, so let's dive into that.

To draw in PyGTK, you need a drawing area, or gtk.DrawingArea(). Since it doesn't size itself to text like a button, you can set its size explicitly. So add this code right after you show the VBox and before you create your button:

# Create an area to draw in:
drawing_area = gtk.DrawingArea()
drawing_area.set_size_request(600, 400)
vbox.pack_start(drawing_area)
drawing_area.show()

You might want to change the name of the button to "Quit" while you're at it. Now you have a much bigger window, like Figure 2.

 

So far, so good. But how do you draw? Surprisingly, you can't draw anything until after the window has been made visible. When does that happen? Not until after you call gtk.main().

gtk.main() is what's called an event loop: it shows your window, then waits for events like mouse clicks or typed letters, until it gets the signal to quit. If you put your drawing code after gtk.main(), it'll be too late because the application is already through.

The key is an expose handler: a function that's called whenever your window is exposed on the desktop. That will happen when you first run the app, and it will also happen any time the window is uncovered by another window, or when you switch to another desktop and then back to the desktop where your program is running. Any time your expose handler is called, you need to redraw whatever you want the window to show. It won't remember what was there before, so your program needs to handle the drawing.

An expose handler looks like this. You can put it right after your click handler.

# This function will be called whenever the drawing area is exposed:
def expose_handler(widget, event) :
w, h = widget.window.get_size()
xgc = widget.window.new_gc()
xgc.set_rgb_fg_color(gtk.gdk.color_parse("red"))
widget.window.draw_line(xgc, 0, 0, w, h)

An expose handler takes two arguments: the widget being exposed -- that's your drawing area -- and the event itself, which you can query for details like whether the whole widget is exposed, or only part of it. That's a lot to cover in an article, so please refer to the resources mentioned on page 2 to learn more.

Click here to see the whole program

Sitemap | Contact Us