Sto cercando di scrivere alcune app del pannello per Ubuntu Mate.
Conosco C/C++ e SDL abbastanza bene.
Ho visto la pagina github delle app del pannello Mate-University, ma non riesco a farlo funzionare correttamente / Sto avendo un po' di tempo con esso.
Mi chiedo solo se esiste una strada facile per scrivere app di pannelli? Non sto parlando dell'utilizzo del programma di avvio delle applicazioni personalizzato, vorrei aggiungere nuove funzionalità al pannello, ma non sono sicuro di come farlo. Un tutorial o una descrizione sulla scrittura di app del pannello potrebbero essere davvero utili.
Migliore risposta
Poiché quella che sembra essere l'occasione per porre questa domanda ha già una risposta, sto rispondendo a questa domanda come una spiegazione estesa su come è stato fatto (in python
)
Base statico indicatore
Poiché Ubuntu Mate, da 15,10, supporta gli indicatori, non c'è molta differenza tra la scrittura di un indicatore e un'app di pannello per Mate. Pertanto, questo collegamento è un buon punto di partenza per un indicatore di base in python
, utilizzando AppIndicator3
API. Il collegamento è un buon inizio, ma non fornisce alcuna informazione su come mostrare il testo sull'indicatore, per non parlare di come aggiornare il testo (o l'icona). Tuttavia, con alcune aggiunte, ciò porta a una "cornice" di base di un indicatore come di seguito. Mostrerà un'icona, un'etichetta di testo e un menu:
#!/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()
Nella riga AppIndicator3.IndicatorCategory.OTHER
, la categoria è definita, come spiegato in questo link (parzialmente obsoleto). Impostare la categoria giusta è importante, a.o. per posizionare l'indicatore in una posizione appropriata nel pannello.
La sfida principale; come aggiornare il testo e/o l'icona dell'indicatore
La vera sfida non è come scrivere un indicatore di base, ma come aggiornare periodicamente il testo e/o l'icona del tuo indicatore, poiché vuoi che mostri l'ora (testuale). Per far funzionare correttamente l'indicatore, non possiamo semplicemente usare il threading
per avviare un secondo processo di aggiornamento periodico dell'interfaccia. Bene, in realtà possiamo, ma su un periodo più lungo, porterà a conflitti, come ho scoperto.
Ecco dove GObject
entra, a, come è messo in questo (anche obsoleto) link:
chiama gobject.threads_init()
all'inizializzazione dell'applicazione. Quindi avvii i thread normalmente, ma assicurati che i thread non eseguano mai direttamente attività della GUI. Invece, usi gobject.idle_add
per pianificare l'esecuzione dell'attività della GUI nel thread principale
Quando sostituiamo gobject.threads_init()
da GObject.threads_init()
e gobject.idle_add
da GObject.idle_add()
, abbiamo praticamente la versione aggiornata di come eseguire i thread in un Gtk
applicazione. Un esempio semplificato, che mostra un numero crescente di scimmie:
#!/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()
Questo è il principio. Nell'indicatore effettivo in questa risposta, sia il tempo di ciclo che il testo dell'indicatore sono stati determinati da un modulo secondario, importato nello script, ma l'idea principale è la stessa.