Python AppIndicator menu freezes

164 views Asked by At

I am trying to create an appindicator with one menu item displaying a variable status message. This works for a while, but then the text of the menu item stops updating. Here's a minimal non-working example that I've created in an attempt to isolate the problem:

#!/usr/bin/python
import threading,time
from gi.repository import Gtk
from gi.repository import AppIndicator3 as AppIndicator

i = 0
def tinker_with_menu_item():
    global i
    while True:
        i = i + 1
        menu_item.get_child().set_text("We are now at " + str(i) + ".")
        menu_item.queue_draw()            ###
        while Gtk.events_pending():       ###
            print "events pending ..."    ###
            Gtk.main_iteration_do(True)   ###
        time.sleep(0.01)

menu_item = Gtk.MenuItem('')
menu = Gtk.Menu()
menu.append(menu_item)
menu.show_all()
appindicator = AppIndicator.Indicator.new("my-app-indicator", Gtk.STOCK_INFO, AppIndicator.IndicatorCategory.SYSTEM_SERVICES)
appindicator.set_menu(menu)
appindicator.set_status(AppIndicator.IndicatorStatus.ACTIVE)
thread = threading.Thread(target=tinker_with_menu_item)
thread.daemon = True
thread.start()       
Gtk.main()

Sometimes, the text in the menu item counts up into the high ten-thousands, sometimes it already stops in the early hundreds. Further details:

  • I added the lines marked ### after reading some proposed solutions in similar stackoverflow questions. However, they don't resolve the issue. The line "events pending ..." never appears in the terminal.
  • Updating a panel icon in a similar way works flawlessly. If I update both a menu item as above and the appindicator's panel icon, the icon keeps updating even after the menu item has frozen.
  • I'm using Python 2.7.6 on Ubuntu 14.04 (Unity desktop).

Any ideas?

1

There are 1 answers

0
Benur21 On

Posting the final answer from Padraic Cunningham and the OP in the comments (it also helped me):

#!/usr/bin/python
import threading, time
import gi
gi.require_version('AppIndicator3', '0.1')
gi.require_version('Gtk', '3.0')
from gi.repository import GLib
from gi.repository import Gtk
from gi.repository import AppIndicator3 as AppIndicator

i = 0
def tinker_with_menu_item():
    global i
    while True:
        i = i + 1
        def update_text():
          menu_item.get_child().set_text("We are now at " + str(i) + ".")
        GLib.idle_add(update_text)
        time.sleep(0.01)

menu_item = Gtk.MenuItem(label='')
menu = Gtk.Menu()
menu.append(menu_item)
menu.show_all()
appindicator = AppIndicator.Indicator.new("my-app-indicator", Gtk.STOCK_INFO, AppIndicator.IndicatorCategory.SYSTEM_SERVICES)
appindicator.set_menu(menu)
appindicator.set_status(AppIndicator.IndicatorStatus.ACTIVE)
thread = threading.Thread(target=tinker_with_menu_item)
thread.daemon = True
thread.start()       
Gtk.main()