How to periodically update Gtk3 Label text?

2019-08-19 08:28发布

问题:

I am writing an app-indicator on Ubuntu 18.04. Getting started was the most difficult part. Docs don't help much. I found this blog and I have a POC that just shows a fixed text on my application bar like this -

What I have not been able to figure out is how to update this text periodically or dynamically to display actual information that I need for example: CPU frequency, temperature etc.

I have looked at the following places, however I think i am missing something.
https://lazka.github.io/pgi-docs/Gtk-3.0/classes/Label.html
https://askubuntu.com/questions/108035/writing-indicators-with-python-gir-and-gtk3
https://lazka.github.io/pgi-docs/AppIndicator3-0.1/classes/Indicator.html#AppIndicator3.Indicator.set_label

The working code that I have is -

import os
import signal
from gi.repository import Gtk as gtk
from gi.repository import AppIndicator3 as appindicator

APPINDICATOR_ID = 'myappindicator'

def main():
    indicator = appindicator.Indicator.new(APPINDICATOR_ID, gtk.STOCK_INFO, appindicator.IndicatorCategory.SYSTEM_SERVICES)
    indicator.set_status(appindicator.IndicatorStatus.ACTIVE)
    indicator.set_menu(build_menu())
    indicator.set_label('world', '8.8')
    gtk.main()

def build_label():
    label = gtk.Label()
    return label

def build_menu():
    menu = gtk.Menu()
    item_quit = gtk.MenuItem('Quit')
    item_quit.connect('activate', quit)
    menu.append(item_quit)
    menu.show_all()
    return menu

def quit(source):
    gtk.main_quit()

if __name__ == "__main__":
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    main()

EDIT:
Referring to this similar SO post, and this apparently working example, I tried adding timeout_add_seconds, and timeout_add however the text doesn't change at all, it displays only the first call. I inserted a print statement there too, and surprisingly, that also prints only once. Don't know why that is happening -
New code attempt-

import random
from gi.repository import Gtk, GLib
from gi.repository import AppIndicator3 as appindicator

APPINDICATOR_ID = 'myappindicator'

def cb_exit(w, data):
   Gtk.main_quit()

def change_label(ind_app):
    text = 'Hello World, what a great day'.split()
    t = random.choice(text)
    print(t)
    ind_app.set_label(t , '')

ind_app = appindicator.Indicator.new(APPINDICATOR_ID, Gtk.STOCK_INFO, appindicator.IndicatorCategory.SYSTEM_SERVICES)
ind_app.set_status(appindicator.IndicatorStatus.ACTIVE)

# create a menu
menu = Gtk.Menu()
menu_items = Gtk.MenuItem("Exit")
menu.append(menu_items)
menu_items.connect("activate", cb_exit, '')
menu_items.show_all()
ind_app.set_menu(menu)
GLib.timeout_add(1000, change_label, ind_app)
Gtk.main()

回答1:

I figured this out myself. I was using the timeout_add function incorrectly. The called function must return anything non false for the timer to continue. In my case it is returning nothing, hence the timer was destroying itself. The docs here and this SO post helped me figure this out. SO the code finally looks like this -

import random
from gi.repository import Gtk, GLib
from gi.repository import AppIndicator3 as appindicator

APPINDICATOR_ID = 'myappindicator'

def change_label(ind_app):
    text = 'Hello world, what a beautiful day'.split()
    t = random.choice(text)
    print(t)
    ind_app.set_label(t , '')
    return True

def quit(source):
    Gtk.main_quit()

ind_app = appindicator.Indicator.new(APPINDICATOR_ID, Gtk.STOCK_INFO, appindicator.IndicatorCategory.SYSTEM_SERVICES)
ind_app.set_status(appindicator.IndicatorStatus.ACTIVE)

# create a menu
menu = Gtk.Menu()
menu_items = Gtk.MenuItem("Exit")
menu.append(menu_items)
menu_items.connect("activate", quit)
menu_items.show_all()
ind_app.set_menu(menu)
GLib.timeout_add(1000, change_label, ind_app)
Gtk.main()