Da die scheinbare Gelegenheit, diese Frage zu stellen, bereits eine Antwort hat , beantworte ich diese Frage als ausführliche Erklärung, wie es gemacht wurde (in python
)
Grundlegende statische Anzeige
Da Ubuntu Mate ab 15,10 Indikatoren unterstützt, gibt es keinen großen Unterschied zwischen dem Schreiben eines Indikators und einer Panel-App für Mate. Daher ist dieser Link ein guter Ausgangspunkt für einen Basisindikator in python
der AppIndicator3
API. Der Link ist ein guter Anfang, enthält jedoch keine Informationen zum Anzeigen von Text auf dem Indikator, geschweige denn zum Aktualisieren des Texts (oder Symbols). Mit ein paar Ergänzungen führt dies jedoch zu einem grundlegenden "Rahmen" eines Indikators wie unten. Es werden ein Symbol, eine Textbeschriftung und ein Menü angezeigt:
#!/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()
In der Zeile AppIndicator3.IndicatorCategory.OTHER
wird die Kategorie definiert, wie in diesem (teilweise veralteten) Link erläutert . Es ist wichtig, die richtige Kategorie einzustellen, um den Indikator an einer geeigneten Stelle im Bedienfeld zu platzieren.
Die Hauptherausforderung; wie man den Anzeigetext und / oder das Symbol aktualisiert
Die eigentliche Herausforderung besteht nicht darin, einen Basisindikator zu schreiben, sondern den Text und / oder das Symbol Ihres Indikators regelmäßig zu aktualisieren , da die (Text-) Zeit angezeigt werden soll. Damit der Indikator ordnungsgemäß funktioniert, können wir nicht einfach threading
einen zweiten Prozess starten, um die Schnittstelle regelmäßig zu aktualisieren. Nun, eigentlich können wir das, aber auf längere Sicht wird es zu Konflikten führen, wie ich herausgefunden habe.
Hier GObject
kommt, wie es in diesem (auch veralteten) Link steht :
Aufruf gobject.threads_init()
bei der Anwendungsinitialisierung. Dann starten Sie Ihre Threads normal, stellen jedoch sicher, dass die Threads niemals direkt GUI-Aufgaben ausführen. Stattdessen gobject.idle_add
planen Sie die Ausführung der GUI-Aufgabe im Hauptthread
Wenn wir gobject.threads_init()
nach GObject.threads_init()
und gobject.idle_add
nach ersetzen GObject.idle_add()
, haben wir so ziemlich die aktualisierte Version, wie Threads in einer Gtk
Anwendung ausgeführt werden. Ein vereinfachtes Beispiel, das eine zunehmende Anzahl von Affen zeigt:
#!/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()
Das ist das Prinzip. Im tatsächlichen Indikator in dieser Antwort wurden sowohl die Schleifenzeit als auch der Indikatortext von einem sekundären Modul bestimmt, das in das Skript importiert wurde, aber die Hauptidee ist dieselbe.