Estoy tratando de escribir algunas aplicaciones de panel para ubuntu Mate.
Conozco C/C++ y SDL razonablemente bien.
He visto la página de github de aplicaciones de panel de Mate-University, pero no puedo hacer que funcione correctamente / Estoy teniendo un tiempo con eso.
Me pregunto si hay alguna vía fácil para escribir aplicaciones de panel. No estoy hablando de usar el iniciador de aplicaciones personalizado, me gustaría agregar una nueva funcionalidad al panel, pero no estoy seguro de cómo hacerlo. Un tutorial o una descripción sobre cómo escribir aplicaciones de panel podría ser muy útil.
Mejor respuesta
Dado que lo que parece ser la ocasión para hacer esta pregunta ya tiene una respuesta, respondo esta pregunta como una explicación extendida sobre cómo se hizo (en python
)
Básico estático indicador
Dado que Ubuntu Mate, desde 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 python
, usando el AppIndicator3
API. El enlace es un buen comienzo, pero no proporciona ninguna información sobre cómo mostrar texto en el indicador, y mucho menos sobre cómo actualizar. el texto (o icono). Sin embargo, con algunas adiciones, esto conduce 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 = "//eadn-wc01-5196795.nxedge.io/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
, la categoría está definida, como se explica en este enlace (parcialmente desactualizado). Establecer la categoría correcta es importante, entre otros. para colocar el indicador en una posición adecuada en el panel.
El principal desafío; cómo actualizar el texto y/o el icono del indicador
El verdadero desafío no es cómo escribir un indicador básico, sino cómo actualizar periódicamente el texto y/o icono de su indicador, ya que desea que muestre la hora (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 más largo plazo, conducirá a conflictos, como descubrí.
Aquí es donde GObject
viene en, a, como se pone en este enlace (también desactualizado):
llamar a gobject.threads_init()
en la inicialización de la aplicación. Luego, inicia sus subprocesos normalmente, pero asegúrese de que los subprocesos nunca realicen ninguna tarea de GUI directamente. En su lugar, usa gobject.idle_add
para programar la tarea GUI para que se ejecute en el hilo principal
Cuando reemplazamos gobject.threads_init()
por GObject.threads_init()
y gobject.idle_add
por GObject.idle_add()
, prácticamente tenemos la versión actualizada de cómo ejecutar subprocesos en un Gtk
solicitud. 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 = "//eadn-wc01-5196795.nxedge.io/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 ciclo como el texto del indicador fueron determinados por un módulo secundario, importado en el script, pero la idea principal es la misma.