What is PyGTK?
PyGTK provides a convenient wrapper for the GTK library for use in Python programs, and takes care of many of the boring details such as managing memory and type casting. More details here.What is Glade?
Glade is a free user interface builder for GTK+ and GNOME, released under the GNU GPL License.The user interfaces designed in Glade are saved as XML, and by using the libglade library these can be loaded by applications dynamically as needed.By using libglade, Glade XML files can be used in numerous programming languages including C, C++, Java, Perl, Python, C#, Pike, Ruby, Haskell, Objective Caml and Scheme. More about Glade here.
...and what about Matplotlib?
Matplotlib is a python 2D plotting library which produces publication quality figures using in a variety of hardcopy formats and interactive GUI environments across platforms. matplotlib can be used in python scripts, interactively from the python shell (ala matlab or mathematica), in web application servers generating dynamic charts, or embedded in GUI applications; see backends. More about this incredible library here.Part One: create the GUI using Glade
Working with Glade is pretty straightforward because you use drag and drop to create a user interface. An important aspect of using PyGTK/Glade is the use of boxes, they are the containers for you widgets such as buttons, labels and list views. Thus they more or less determine the layout (and therefore the usability) of your application.Now, create a new project in Glade and select a window from the Palette. This new window is the main window of your application, the parent. Select a notebook from the palette and drop it on the main window, the notebook book should hold 3 pages. Use the Properties window to change the amount of pages. By now you are probably aware of the enormous power of glade, it is really very intuitive to build GUI's like this. Every page of the notebook has boxes to contain the various widgets used in our little tutorial. This is illustrated below, it is a screenshot of the Widget Tree and the Properties window.

Another important element of Glade are Signals because they connect a user action (eg. clicked) to a callback (or function). Add a button to hbox1 as shown in the Widget Tree depicted above. After you've added the button (which will be named button1 by default), click on it and the Properties of button1 will pop up. Now click on the Signals tab of the Properties window and add the signal "clicked", the handler "on_button1_clicked" is suggested by Glade, leave it as is.
Connect Glade to Python
Now, that's a very nice interface but apart from being nice there is not much you can do with it and this part of the tutorial will tell you how. But first, let's take a look at the required libraries (or modules if you prefer) to run our little app:- sys, to be able to use sys.exit(1) terminates Python in midflight if some requirements regarding GTK are not met
- some functions that use a database to store and retrieve data (in this case DBStuff, it uses MySQLdb)
- matplotlib, to create them beautiful plots
- pygtk
| 1 | !/usr/bin/env python |
| 2 | import sys |
| 3 | import DBStuff |
| 4 | |
| 5 | import matplotlib |
| 6 | matplotlib.use('GTK') |
| 7 | from matplotlib.figure import Figure |
| 8 | from matplotlib.axes import Subplot |
| 9 | from matplotlib.backends.backend_gtk import FigureCanvasGTK, NavigationToolbar |
| 10 | from matplotlib.numerix import arange, sin, pi |
| 11 | |
| 12 | try: |
| 13 | import pygtk |
| 14 | pygtk.require("2.0") |
| 15 | except: |
| 16 | pass |
| 17 | try: |
| 18 | import gtk |
| 19 | import gtk.glade |
| 20 | except: |
| 21 | sys.exit(1) |
| view plain | print | copy to clipboard | ? |
| 22 | class appGui: |
| 23 | def __init__(self): |
| 24 | gladefile = "project2.glade" |
| 25 | self.windowname = "gtkbench" |
| 26 | self.wTree = gtk.glade.XML(gladefile, self.windowname) |
| 27 | dic = {"on_window1_destroy" : gtk.main_quit, |
| 28 | "on_button1_clicked" : self.submitDB, |
| 29 | "on_button3_clicked" : self.fillTree, |
| 30 | "on_notebook1_switch_page" : self.selectNotebookPage, |
| 31 | "on_treeview1_button_press_event" : self.clickTree, |
| 32 | "on_button2_clicked" : self.createProjectGraph |
| 33 | } |
| 34 | self.wTree.signal_autoconnect(dic) |
| view plain | print | copy to clipboard | ? |
The next part will display a Matplotlib bar chart on the first page of the notebook. Now how, you might wonder, does this bar chart know where it should be displayed? Examine the code:
| 35 | # setup matplotlib stuff on first notebook page (empty graph) |
| 36 | self.figure = Figure(figsize=(6,4), dpi=72) |
| 37 | self.axis = self.figure.add_subplot(111) |
| 38 | self.axis.set_xlabel('Yepper') |
| 39 | self.axis.set_ylabel('Flabber') |
| 40 | self.axis.set_title('An Empty Graph') |
| 41 | self.axis.grid(True) |
| 42 | self.canvas = FigureCanvasGTK(self.figure) # a gtk.DrawingArea |
| 43 | self.canvas.show() |
| 44 | self.graphview = self.wTree.get_widget("vbox1") |
| 45 | self.graphview.pack_start(self.canvas, True, True) |
| view plain | print | copy to clipboard | ? |
The next thing we want to do is setting up a listview on the second page of the notebook. A listview consists of columns and rows to store data similar to Calc and Excel. We want to do several things: fill the cells of the listview with data, click on the column header to sort the data and click on the header to create a graph. Below you will find the code to create the first column, please take a look at the link to the source code at the end of this tutorial for the next three columns.
| 46 | self.listview = self.wTree.get_widget("treeview1") |
| 47 | self.listmodel = gtk.ListStore(str, int, int, str, str) |
| 48 | self.listview.set_model(self.listmodel) |
| 49 | renderer = gtk.CellRendererText() |
| 50 | column = gtk.TreeViewColumn("Name",renderer, text=0) |
| 51 | column.set_clickable(True) |
| 52 | column.set_sort_column_id(0) |
| 53 | column.connect("clicked", self.createDBGraph) |
| 54 | column.set_resizable(True) |
| 55 | self.listview.append_column(column) |
| view plain | print | copy to clipboard | ? |
Let's examine this callback in the next lines of code:
| 56 | def createDBGraph(self, widget): |
| 57 | self.axis.clear() |
| view plain | print | copy to clipboard | ? |
| 58 | self.axis.set_xlabel('Samples (n)') |
| 59 | self.axis.set_ylabel('Value (-)') |
| 60 | self.axis.set_title('Another Graph (click on the columnheader to sort)') |
| 61 | self.axis.grid(True) |
| 62 | # get columns from listmodel |
| 63 | age = [] |
| 64 | for row in self.listmodel: |
| 65 | age.append(row[1]) |
| 66 | size = [] |
| 67 | for row in self.listmodel: |
| 68 | size.append(row[2]) |
| view plain | print | copy to clipboard | ? |
| 69 | # get number of rows |
| 70 | N = len(age) |
| 71 | ind = arange(N) # the x locations for the groups |
| 72 | width = 0.35 # the width of the bars |
| view plain | print | copy to clipboard | ? |
| 73 | p1 = self.axis.bar(ind, age, width, color='b') |
| 74 | p2 = self.axis.bar(ind+width, size, width, color='r') |
| view plain | print | copy to clipboard | ? |
| 75 | # destroy graph if it already exists |
| 76 | while True: |
| 77 | try: |
| 78 | self.canvas2.destroy() |
| 79 | break |
| 80 | except: |
| 81 | print "nothing to destroy" |
| 82 | break |
| 83 | self.canvas2 = FigureCanvasGTK(self.figure) # a gtk.DrawingArea |
| 84 | self.canvas2.show() |
| 85 | self.grahview = self.wTree.get_widget("vbox2") |
| 86 | self.grahview.pack_start(self.canvas2, True, True) |
| view plain | print | copy to clipboard | ? |
The source code for this tutorial is available here And the glade xml file is available here
discuss this topic to forum
