Dado que lo que parece ser la ocasión para hacer esta pregunta ya tiene una respuesta , estoy respondiendo esta pregunta como una explicación extendida sobre cómo se hizo (en python
)
Indicador estático básico
Dado que Ubuntu Mate, de 15,10, admite indicadores, no hay mucha diferencia entre escribir un indicador y una aplicación de panel para Mate. Por lo tanto, este enlace es un buen punto de partida para un indicador básico en el python
uso de la AppIndicator3
API. El enlace es un buen comienzo, pero no proporciona ninguna información sobre cómo mostrar el texto en el indicador, y mucho menos cómo actualizar el texto (o icono). Sin embargo, con algunas adiciones, esto lleva a un "marco" básico de un indicador como se muestra a continuación. Mostrará un icono, una etiqueta de texto y un menú:
#!/usr/bin/env python3
import signal
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3
class Indicator():
def __init__(self):
self.app = 'test123'
iconpath = "/opt/abouttime/icon/indicator_icon.png"
self.indicator = AppIndicator3.Indicator.new(
self.app, iconpath,
AppIndicator3.IndicatorCategory.OTHER)
self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
self.indicator.set_menu(self.create_menu())
self.indicator.set_label("1 Monkey", self.app)
def create_menu(self):
menu = Gtk.Menu()
# menu item 1
item_1 = Gtk.MenuItem('Menu item')
# item_about.connect('activate', self.about)
menu.append(item_1)
# separator
menu_sep = Gtk.SeparatorMenuItem()
menu.append(menu_sep)
# quit
item_quit = Gtk.MenuItem('Quit')
item_quit.connect('activate', self.stop)
menu.append(item_quit)
menu.show_all()
return menu
def stop(self, source):
Gtk.main_quit()
Indicator()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()
En la línea AppIndicator3.IndicatorCategory.OTHER
, se define la categoría, como se explica en este enlace (parcialmente desactualizado) . Es importante establecer la categoría correcta para poner el indicador en una posición adecuada en el panel.
El principal desafío; Cómo actualizar el texto indicador y / o el ícono
El verdadero desafío no es cómo escribir un indicador básico, sino cómo actualizar periódicamente el texto y / o el icono de su indicador, ya que desea que muestre el tiempo (textual). Para que el indicador funcione correctamente, no podemos simplemente usar threading
para iniciar un segundo proceso para actualizar periódicamente la interfaz. Bueno, en realidad podemos, pero a largo plazo, conducirá a conflictos, como descubrí.
Aquí es donde GObject
entra, a, como se coloca en este enlace (también desactualizado) :
llame gobject.threads_init()
a la solicitud de inicialización. Luego inicia sus hilos normalmente, pero asegúrese de que los hilos nunca realicen ninguna tarea de GUI directamente. En su lugar, se utiliza gobject.idle_add
para programar la tarea GUI para que se ejecute en el hilo principal
Cuando se reemplaza gobject.threads_init()
por GObject.threads_init()
y gobject.idle_add
por GObject.idle_add()
, prácticamente sólo tenemos la versión actualizada de cómo ejecutar subprocesos en una Gtk
aplicación. Un ejemplo simplificado, que muestra un número creciente de monos:
#!/usr/bin/env python3
import signal
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3, GObject
import time
from threading import Thread
class Indicator():
def __init__(self):
self.app = 'test123'
iconpath = "/opt/abouttime/icon/indicator_icon.png"
self.indicator = AppIndicator3.Indicator.new(
self.app, iconpath,
AppIndicator3.IndicatorCategory.OTHER)
self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
self.indicator.set_menu(self.create_menu())
self.indicator.set_label("1 Monkey", self.app)
# the thread:
self.update = Thread(target=self.show_seconds)
# daemonize the thread to make the indicator stopable
self.update.setDaemon(True)
self.update.start()
def create_menu(self):
menu = Gtk.Menu()
# menu item 1
item_1 = Gtk.MenuItem('Menu item')
# item_about.connect('activate', self.about)
menu.append(item_1)
# separator
menu_sep = Gtk.SeparatorMenuItem()
menu.append(menu_sep)
# quit
item_quit = Gtk.MenuItem('Quit')
item_quit.connect('activate', self.stop)
menu.append(item_quit)
menu.show_all()
return menu
def show_seconds(self):
t = 2
while True:
time.sleep(1)
mention = str(t)+" Monkeys"
# apply the interface update using GObject.idle_add()
GObject.idle_add(
self.indicator.set_label,
mention, self.app,
priority=GObject.PRIORITY_DEFAULT
)
t += 1
def stop(self, source):
Gtk.main_quit()
Indicator()
# this is where we call GObject.threads_init()
GObject.threads_init()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()
Ese es el principio. En el indicador real de esta respuesta , tanto el tiempo de bucle como el texto del indicador fueron determinados por un módulo secundario, importado en el script, pero la idea principal es la misma.