I do what I can

Random thoughts from Mauricio Teixeira…

Gnome Notification Area Application in Python (English)

with 13 comments

It’s nice how many of your preferred Gnome applications can fall back into a small icon on the notification area (also called tray), and conveniently sit there until something happens. Have you ever wondered how to do that in Python?

This is a not-so-quick and not-so-dirty demonstration of how to write a small Gnome Python application that will sit in the Gnome notification area (which we will also call “tray”), and react to some menu actions.

You can find the full code by downloading this file:
hello-tray.py

Below I will comment the most important parts of the code, so that you understand the basics, and create your own code from there.

First of all, bare with me, I decided to make the application fully object-oriented because it’s then easier to extend, and add more features later. Also, it’s a good exercise to write even the simplest applications using OOP, since the most complex ones will be easier to maintain if you do so, and practice takes you to perfection (well, at least to better practice). Also, notice I’m a free-time developer (my primary job is system administration), so many things here might be poorly explained or poorly coded, but the general guidance is what matters. Let’s move on.

I will explain how the code works by following the regular flow of the code, like how it would be executed in our test environment. Each number in the beginning of a line of code means the line number on the actual file (so that you can follow easily).

The code starts with a simple Python statement that will tell us which one is the main application object.

71: if __name__ == "__main__":
72:   helloWord = HelloTray()

The class declaration starts on line 6. Notice that apart from what you expected, the class does not need to be a derivation of anything else. This happens because the application itself is not on the notification area, but rather it’s the interface which sits in there. So we need to create that interface.

31:  def __init__(self):
32:    self.statusIcon = gtk.StatusIcon()
33:    self.statusIcon.set_from_stock(gtk.STOCK_ABOUT)
34:    self.statusIcon.set_visible(True)
35:    self.statusIcon.set_tooltip("Hello World")

The class initialization code starts by creating a gtk.StatusIcon widget. That’s the “magic” that creates the tray icon. This is just like if you were creating your main gtk.Window in a regular PyGTK application. Then we need to define some properties for that status icon. In this particular case we use the stock GTK icons, just to make our lives easier. Another advantage of using stock icons, is that your application will seamlesly fit into which ever theme is currently active. The tool tip property on line 35 sets the text that will show when we hover the mouse over the icon.

37:    self.menu = gtk.Menu()
38:    self.menuItem = gtk.ImageMenuItem(gtk.STOCK_EXECUTE)
39:    self.menuItem.connect('activate', self.execute_cb, self.statusIcon)
40:    self.menu.append(self.menuItem)
41:    self.menuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
42:    self.menuItem.connect('activate', self.quit_cb, self.statusIcon)
43:    self.menu.append(self.menuItem)

Now we need to create a pop up menu, that will be shown when we right-click over the status icon. We use the standard gtk.Menu widget. The gtk.ImageMenuItem widget creates a menu item with a small icon and a caption. In this case we’re also using stock items just to wrap up quickly. Notice that for each menu item, there is an associate call back method (self.execute_cb and self.quit_cb), which will be called whenever the user clicks that. Those are the real “actions” on our small application.

45:    self.statusIcon.connect('popup-menu', self.popup_menu_cb, self.menu)
46:    self.statusIcon.set_visible(1)
47:
48:    gtk.main()

Now we need to connect the menu with the “pop-up” action from the status icon widget. This also triggers an associated call back method (self.popup_menu_cb) that will show the pop-up menu (line 41 on the code).

Line 48 on the code starts the main GTK iteration, that makes all the visible widgets to show. In this case, the icon now shows on the notification area. Right-click on the icon, and you will see the beautiful pop-up menu.

68:        data.popup(None, None, gtk.status_icon_position_menu,
69:                   3, time, self.statusIcon)

I would like to make a small comment on that part of the code. The gtk.status_icon_position_menu is a call back method associated with showing up the menu that works as a helper to verify where to position the pop-up menu itself. Without that call back, the pop-up will show exactly below the mouse cursor, exactly where the icon has been clicked. With this call back, the menu beautifully shows below the icon, out of the panel bar (if the panel that holds the notification area is on the top, or above the icon if it’s on the bottom). That looks much more professional.

The execute_cb method on line 50 creates a standard gtk.Window, with a standard gtk.Button, that will greet the world to prove our application works fine.

The quit_cb method on line 61 simply shuts down the whole thing (closes the window, if open, and terminates the tray icon).

Well, I think that’s it! The intention here was just to show you how easy it is to place your application on the notification area, and point you our to the necessary widgets needed for the task. From here, you’re free to create your own applications.

By the way, feel free to comment below, and ask any questions. I’ll be very glad to help you.

See you around!😉

Written by netmask

abril 18, 2009 às 13:00

Publicado em linux

Tagged with , , , ,

13 Respostas

Subscribe to comments with RSS.

  1. Thanks, I found this really helpful!

    Shane

    abril 27, 2009 at 11:20

  2. Thanks for the help!

    Blaise Alleyne

    maio 17, 2009 at 01:18

  3. Nice stuff!
    I believe it would be helpful if you add

    self.menuItem.connect(‘activate’, self.execute_cb, self.statusIcon)

    .

    g00se

    junho 12, 2009 at 11:07

  4. Hi Mauricio, it’s a great article.

    However, Is there anyway to popping-up the menu when the user left click the status icon instead of right click ?? I’ve modified your source to this purpose but still nothing happen. I’ve changed the signal from “popup-menu” to “activate” and do little bit update at “popup_menu_cb” function, but I got nothing. The menu just wont show up.

    And, I think, “popup-menu” signal only produce right click status, the “button” at your function will always be equal to 3. So maybe we can remove the validation there.

    btw, I’m running your source at Ubuntu. Thanx before

    Riki Pribadi

    julho 15, 2009 at 00:49

  5. Ahh…never mind, I found a way out on another search at google, facebook-notify.py.
    anyway, I can use “activate” signal, but the problem is the “time” variable value. When we use “popup-menu” signal, the “time” value is passed as one of arguments, but when we use “activate” signal, it is not. So I need to use gtk.get_current_event_time() as our “time” variable. This is how it looks like:
    data.popup(None, None, gtk.status_icon_position_menu, 1, gtk.get_current_event_time(), self.statusIcon)

    Cheers, and keep up the good work.

    Riki Pribadi

    julho 15, 2009 at 01:09

  6. Just curious what license this example is under, if any.

    Jamin Collins

    dezembro 19, 2009 at 16:39

  7. @Jamin Collins
    There is no license attached to the code. Just use it. Have fun.🙂

    netmask

    dezembro 20, 2009 at 16:20

  8. > There is no license attached to the code. Just use it. Have fun.

    Yeah, but that would be copyright law violation in most countries. Unless you explicitly put the code in the public domain or grants some kind of license, nobody can legally use the code.

    Since the code is rather small, you’d probably have no chance in the court (not that you would sue anyone, right?), but still… people should get used to sticking “you are free to use this code under the terms of MIT license”/”this code is in public domain” on stuff… Or change the law. Take your pick.

    Mordae

    junho 24, 2010 at 10:24

  9. […] Gnome Notification Area Application in Python (English) abril, 2009 9 comentários 3 […]

  10. […] in Python. I started with this great tutorial that I found after doing some Google searches, Gnome Notification Area Application in Python. This is a great starting point for building applets for the Notification […]

  11. I was looking for quite some time for an example that showed how to launch the popup menu using the left click.
    Turns out I had to launch the __on_activate__ (activate connector) using parameters: self.menu, 3, gtk.get_current_event_time())

    With 3 being the right-click button I’m guessing.
    Still new at python, but this helped a ton!

    Dann

    março 24, 2011 at 18:23

  12. Simple and works like a charm. Thanks, great example!

    JustChecking

    maio 23, 2011 at 10:31


Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: