Creating a GUI using PyGTK and Glade

After spending some time creating a GUI using TKinter and having it be pretty easy, but getting frustrated by how linked my code and the GUI was, I decided to look into creating a GUI using another toolkit. After looking around at the options for a while I settled on using PyGTK and Glade

The reason I decided upon using these two technologies is because they are cross platform and using GLADE satisfies my wish to separate the code form the GUI.

If you’ve never heard of Glade before, it’s “a User Interface Builder for GTK+ and GNOME”. It generates XML files which describe the desired GUI.

I’ll let the pyGTK website describe what PyGTK is:

PyGTK provides a convenient wrapper for the GTK+ library for use in Python programs, taking care of many of the boring details such as managing memory and type casting. When combined with PyORBit and gnome-python, it can be used to write full featured Gnome applications.

So there you go, I’m writing this on my freshly installed Debian system. If you are running Debian, or a Debian based distribution getting PyGTK and Glade is pretty simple:
[code]
apt-get install python-gtk2 python-glade2
[/code]

Now lets create our first simple GUI, this is what you will be greeted with when you first start GLADE:

Python RSS Reader

What we need to do is press the “Window” button on the GLADE palette to create our base window. We can then edit the properties of the window in the Properties Window:

Python RSS Reader

We’ll call our window MainWindow and we will set the title to be “Hello World… Again!”.

If you are used to using an integrated GUI builder, for example Visual Studio, using glade might feel a bit strange the first few times. Especially since you don’t actually place your controls anywhere you want on the screen, instead you “pack” them. Strangely enough (at least for me) it actually seems like this is the way the most GUI builders work and applications like Visual Studio are actually the odd ones.

Either way back to the tutorial, the first thing we are going to do is add a label to tell the user to click the button (of course we could just put this text on the button, but how much fun is only one widget?). Since GTK used containers to pack widgets the first thing that we need to do is add a container. We are going to place the label above the Button so we will use a Vertical Box with two rows. To add the vertical Box, simply click on it in the Glade Pallet, and then click on our main window. A small dialog will come up and ask you how many rows you want, we want two in this case.

The next thing we’ll do is add the label by clicking on the label button in the GLADE pallet and then click on the first row in the container that we just created. We’ll keep the default name (label1) but we will change the text to be: “Please click on the button!”. Changing the text is done in the Glade Properties window, which if you have not noticed by now, displays, and allows you to edit, the properties of the currently selected widget.

The next thing we’ll do is add a button in the same way that we added the Label widget except we will add it in the second row. We will call the button btnHelloWorld, and set it’s label to be “Click me!”

We now need to set our project options, I’m going to call this project “pyhelloworld” and save it in my projects/PyHelloWorld folder.

Python RSS Reader

Note: Be sure to set the Visible option for the MainWindow to Yes, on the Common tab of the Window or your main window won’t be visible! This is especially important if you are using Glade3!

So that’s it, you’ll see in the PyHelloWorld folder, that two files have been created, one is the glade project file and has the .glade extension, and the other is our glade GUI XML file with the extension .gladep.

Now we need to create a python program that will load the glade file and display it. So in the same folder I am going to create a file called PyHelloWorld.py.

PyGame Window

Now the first thing we are going to have to do is import all of the libraries that we need for our project:

[code lang=”python”]
#!/usr/bin/env python

import sys
try:
import pygtk
pygtk.require(“2.0″)
except:
pass
try:
import gtk
import gtk.glade
except:
sys.exit(1)
[/code]

The next thing that we need to do is create our main class, I’m going to call it HellowWorldGTK. The we will use the __init__ function to load our glade file:

[code lang=”python”]
class HellowWorldGTK:
“””This is an Hello World GTK application”””

def __init__(self):

#Set the Glade file
self.gladefile = “pyhelloworld.glade”
self.wTree = gtk.glade.XML(self.gladefile)

#Get the Main Window, and connect the “destroy” event
self.window = self.wTree.get_widget(“MainWindow”)
if (self.window):
self.window.connect(“destroy”, gtk.main_quit)
[/code]

The first thing that we do (after defining the class) is specify the glade file that we are going to use and create a gtk.glade.XML object using our glade file. Here is a description of the object taken from the pyGTK2 reference:

This object represents an `instantiation’ of an XML interface description. When one of these objects is created, the XML file is read, and the interface is created. The gtk.glade.XML object then provides an interface for accessing the widgets in the interface by the names assigned to them inside the XML description.

The gtk.glade.XML object can also be used to connect handlers to the named signals in the description. Libglade also provides an interface by which it can look up the signal handler names in the program’s symbol table and automatically connect as many handlers up as it can that way.

So what we are doing when we create our gtk.glade.XML object is creating and loading our main interface.

The next thing that we go is get an instance to our main window and connect the “destroy” event with the get.main_quit() function. This basically quits our application when the main window is closed. Otherwise the application will continue to run when the main window is closed (which we obviously don’t want).

That’s it for our HellowWorldGTK class, the next thing that we need to do is create an instance of our class and then start the GTK main loop:

[code lang=”python”]
if __name__ == “__main__”:
hwg = HellowWorldGTK()
gtk.main()
[/code]

That’s it, pretty easy so far, if you run this file you will be greeted with our little GTK window that doesn’t do anything yet except quit properly when you close the window.

PyGame Window

The next step is to connect the button click event to a function. To do this we will need to use Glade again to edit our interface.

In the main window we need to select our button object and then in the properties Window select the “Signals” tab. There we will add a new signal by clicking on the signal browse button (…) and selecting “clicked”. This will create a handler called “on_btnHelloWorld_clicked” by default. We could change the name of this handler if we wanted but for now the default is good enough.

PyGame Window

That’s it for the work in Glade, now what we need to do is connect that event to something in our code. Fortunately this is pretty easily done using the gtk.glade.XML.signal_autoconnect function.

[code lang=”python”]
#Create our dictionay and connect it
dic = { “on_btnHelloWorld_clicked” : self.btnHelloWorld_clicked,
“on_MainWindow_destroy” : gtk.main_quit }
self.wTree.signal_autoconnect(dic)
[/code]

Basically the dictionary is created using the name of the event, and the function to connect it to. You can see that we connect our button’s click event with a new function, and that we connect the “on_MainWindow_destroy” event with the gtk.main_quit() function, this basically is a replacement for our earlier code that quit the program when the window is closed. Important: If you want to use that version of the dictionary you should go and add the destroy event to the main window in glade.

Note: Since this was missed by people I’ve added some images to make it more obvious what event to connect to:

PyGTK Window

Glade Window

The next thing to do is create our btnHelloWorld_clicked function to the HellowWorldGTK class:

[code lang=”python”]
def btnHelloWorld_clicked(self, widget):
print “Hello World!”
[/code]

Pretty simple! Now when we run it, and click on the “Click Me!” button we see “Hello World!” written our to the command line.

That’s it for this lesson, but so far I really like what I see working with PyGTK and Glade. Here is the full source:

[code lang=”python”]
#!/usr/bin/env python

import sys
try:
import pygtk
pygtk.require(“2.0″)
except:
pass
try:
import gtk
import gtk.glade
except:
sys.exit(1)

class HellowWorldGTK:
“””This is an Hello World GTK application”””

def __init__(self):

#Set the Glade file
self.gladefile = “pyhelloworld.glade”
self.wTree = gtk.glade.XML(self.gladefile)

#Create our dictionay and connect it
dic = { “on_btnHelloWorld_clicked” : self.btnHelloWorld_clicked,
“on_MainWindow_destroy” : gtk.main_quit }
self.wTree.signal_autoconnect(dic)

def btnHelloWorld_clicked(self, widget):
print “Hello World!”

if __name__ == “__main__”:
hwg = HellowWorldGTK()
gtk.main()
[/code]

Helpful links:

http://www.linuxjournal.com/article/6586
http://www.async.com.br/~kiko/pygtk-web/articles/bitpodder/BitPodder.htm
http://www.linuxjournal.com/article/7421
http://www.pygtk.org/articles.html
http://www.pygtk.org/tutorial.html

172 thoughts on “Creating a GUI using PyGTK and Glade”

  1. Thanks for this tutorial….I am new to pyGTK and i was looking for some basic things….and i got the same… :)

    Thanks Again!!

  2. Thanks for the great intro to PyGTK+Glade. I have been convinced that this combo is right for me, but hadn’t learned how to use it until I found your tutorial. I replicated your trial program without issue, and learned a lot along the way.

    I do, however have one curiosity, which is only remotely related to this tutorial. How do you get your syntax highlighted Python code embedded in text boxes? I would be very happy to learn how to do this with my own blog eventually. An email would be much appreciated, if you have the time. Don’t feel obligated.

  3. Hi Milinda,

    How are you trying to insert the notebook into your program? What happens when you try to insert the notebook? Do you get any errors or does it just not show up?

    You might want to try asking on the forums so that more people can find it.

  4. Great tutorial. But since half the battle is getting set up properly with the modules and runtime, it’s probably not good to hide the import exceptions like that. Try it flat:

    import sys
    import pygtk; pygtk.require(“2.0″)
    import gtk
    import gtk.glade

    If any part of the setup is funky, the traceback written to the console will be helpful in figuring out the problem.

  5. Hi,

    My name is Ed, I am really new to Python. I have had it for…oh 3 days. Before attempting Python I did most of my Interfacing with JB. I am using Windows and my console looks slightly different than yours, in your tutorial. I get down as far as saving my project with the extensions Glade and Gladep. I have no Gladep in my folder. Do I need to get an xml editor as well. I am confused here!

    Big thanks

    Ed

  6. Hi Eric,

    You raise a very good point I have changed this sort of code in my later scripts. I realized how frustrating it was when I encounter problems. Thanks for the tip!.

  7. Hi Ed,

    By this time I’m assuming that you are using Glade 3.0, and in Glade 3.0 you only get one file: a .glade file, so don’t worry that you done see a .gladep file.

  8. Instead of doing this manually in code:
    self.window.connect(“destroy”, gtk.main_quit)

    Just set it in Glade widget property dialog signals tab.

  9. Great tutorial! I’m an absolute beginner when it comes to writing applications on Linux/Unix, but this tutorial did a good job in helping me write my first Linux application with a GUI. Hope to see more of this soon.

  10. Thanks! I’ve been looking around for a nice beginners tutorial. One trivial comment, in your python code the glade file is in lower case – pyhelloworld.glade, but in your tutorial you refer to saving it as PyHelloWorld.glade (which is what I saved it as). Because I cut and paste to create the program, rather than just compiling your files, the naming mismatch broke the program. I know it’s easy fixed…but might throw a real beginner

  11. `pygtk.require` inside a try-except-block does not make no sense at all because `pygtk.require` raises an AssertionError if the required version doesn’t match with the versions installed, which would be caught by the except-block.

  12. Hi Trundle,

    Thanks for the comment. In general I think it’s a mistake to have the imports in a try-except block the way that I do in this tutorial, unless it’s for an optional module. This tutorial is just a bit old and I thought I was being smart at the time. Thanks for the information!

  13. Hi, just wanted to say thanks – nice article.

    Coming from a .net, VB, c#, delphi background I found the interface quite alien to start with, but once I saw it as HTML (the layout is similar to the older style HTML) then it all made sense.

    I couldn’t get Glade/gtk2 working in Windows (something to do with a version of GIMP I think), but at home using Ubuntu (Gnome) it works just fine.

    Can’t wait to get really moving with this, so thank you once again.

  14. There is also a utility called GladeGen. It is from a previous LinuxJournal article. It will take in a .glade file and create all of the skeleton code for you. Then all that needs to be done is to implement the signal handlers.

    I don’t know if it works with Glade 3 yet, but its saves a lot of time with Glade 2.

    Conlaoch

  15. Great idea for a tutorial; I just wish I could get a window to appear!

    I’m running xandros linux and have python-gtk2 and python-glade2 installed. The .py, .glade and the .gladep files are in the same folder. MainWindow is set to visible.

    Just can’t think of anything else!

  16. Hi Brin,

    What happens when you run the code? Does it hang or does it just quit? You might try running the following code and seeing where it goes wrong:


    #!/usr/bin/env python

    import sys
    import pygtk
    pygtk.require("2.0")
    import gtk
    import gtk.glade

    class HelloWorldGTK:
    """This is an Hello World GTK application"""

    def __init__(self):

    #set the Glade file
    print "#1"
    self.gladefile = "pyhelloworld.glade" #1
    print "#2"
    self.wTree = gtk.glade.XML(self.gladefile) #2

    #get the Main Window, and connect the "destroy" event
    print "#3"
    self.window = self.wTree.get_widget("MainWindow") #3

    if(self.window):
    print "#4"
    self.window.connect("destroy", gtk.main_quit) #4
    else:
    print "#5"

    if __name__ == "__main__":
    print "#6"
    hwg = HelloWorldGTK() #6
    print "#7"
    gtk.main() #7

  17. Hi….thanks for your reply. This did work and so looking more closely at my code I found that the def __init__(self): had not been indented and this was not trapped by python. Success at last!

    Incidentally I find that in addition to a .glade file I have .glade.bak plus two new folders po and src and several other files e.g. stamp-h.in. Are these documented anywhere and are they useful?

    Cheers…….Brin

  18. Hi,

    Great tutorial! I’ve been trying to make sense of how to use glade for a long time and not succeeding until I found your blog. Thanks!

  19. Nice tutorial! I am new in programming with python. I did my first python experience with pyDev and eclipse on Windows machine.
    I am going through you tutorial and stack at the point when I have to save my project. I don’t have the option to save the project as python project. There are only possibilities for C, C++ and adda 95.
    Please give me a hint what I did wrong?

    Thank
    JonBob

    Sorry for the bad English … I am still learning 😉

  20. Hi JonBob,

    I’m not really sure. To be honest it’s been a long time since I used pyDev and eclipse. In the end I found it too cumbersome, try using geany, it’s my personal favourite these days.

  21. Hi,

    I was having the same problem as some others, where the program wouldn’t quit after I destroyed the window and I had to press control-C. I figured out what was wrong with my code and I thought I would mention it. It was a dumb error, but…

    The main window of my application was not named “MainWindow”, it was named “window1″. So the line about self.wTree.get_widget(“MainWindow”) returned nothing. Then, since there was an if statement around self.window.connect(“destroy”, gtk.main_quit), it silently didn’t connect the event to anything. It might be clearer to leave out that if statement, so that if something’s wrong it’s easier to see it.

    Anyway, thanks so much for the tutorial! I’ve been wishing that I could find good GUI programming opportunities in Python, and this seems like a really good step in that direction.

    -Thomas

  22. Hi, after following this tutorial, I’ve managed to make some small programs. Now I want one that edits a text file, by getting the contents of three text boxes then pasting them into the file. How would I go about this? I can guess, but I’d probably be wildly out. I don’t really need specifics, just the basic code needed in order to do so.

    Preferably by putting the contents of text boxes into a variable, then pasting the contents of the variable into the text file. I can do the latter part, but the former part stumps me. Any help would be appreciated.

    -Bal

  23. Great tutorial. I’ve just started exploring python with glade-3. It works well after turning on \visible\ at the common tab. Also I have to save the glade file as libglade.

    Thanx for the tutorial!!!

    -Drayze

  24. Yes nice intro tutorial..Thank you..

    My .glade file is in the same folder as the .py.

    but python says that it can’t find the glade file .

    one of the posts above also deals with this..

    ….on Windows XP 32

    Everything works if I give a full path name.
    Not sure if this is the correct thing to do. Absolute beginner here:)

  25. Simple and wonderful tutorial. Thanks a bunch for taking your time to post it.

    I did ran into the

    “RuntimeError: could not create GladeXML object” problem that @Diego and few others got. I am using Glade 3.6.3 on Ubuntu 9.04. The problem was with glade project file format. Glade 3.6.3 offers couple of options: GtkBuilder and libglade. To use it with PyGtk programs, the format should be “libglade” (by default GtkBuilder is selected). Changing this got the program running.

  26. Hi —

    Tried your code and originally got the window to appear, then tried to adjust the names to start building my own app and now the code runs and immediately terminates without error but never shows me a window. Here’s what I did:

    import sys
    try:
    import pygtk
    pygtk.require(“2.0″)
    except:
    pass
    try:
    import gtk
    import gtk.glade
    except:
    sys.exit(1)

    class HellowWorldGTK:
    “””This is an Hello World GTK application”””

    def __init__(self):

    #Set the Glade file
    self.gladefile = “glade1.glade”
    self.wTree = gtk.glade.XML(self.gladefile)

    self.window = self.wTree.get_widget(“window1″)
    if (self.window):
    self.window.connect(“destroy”, gtk.main_quit)

    #Create our dictionay and connect it
    dic = { “on_button1_clicked” : self.button1_clicked,
    “on_window1_destroy” : gtk.main_quit }
    self.wTree.signal_autoconnect(dic)

    def button1_clicked(self, widget):
    print “Hello World!”

    if __name__ == “__main__”:
    hwg = HellowWorldGTK()
    gtk.main()

    Any thoughts?
    Thanks,
    Scott

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>