Ponieważ wydaje się, że jest to okazja, aby zadać to pytanie, ma już odpowiedź , odpowiadam na to pytanie jako rozszerzone wyjaśnienie, w jaki sposób zostało to zrobione (w python
)
Podstawowy wskaźnik statyczny
Ponieważ Ubuntu Mate od 15,10 obsługuje wskaźniki, nie ma dużej różnicy między pisaniem wskaźnika a aplikacją panelową dla Mate. Dlatego ten link jest dobrym punktem wyjścia dla podstawowego wskaźnika python
przy użyciu AppIndicator3
interfejsu API. Link jest dobrym początkiem, ale nie zawiera żadnych informacji na temat sposobu wyświetlania tekstu na wskaźniku, ani tym bardziej na temat aktualizacji tekstu (lub ikony). Niemniej jednak, z kilkoma dodatkami, prowadzi to do podstawowej „ramki” wskaźnika, jak poniżej. Wyświetli ikonę, etykietę tekstową i 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 = "/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()
W linii AppIndicator3.IndicatorCategory.OTHER
kategoria jest zdefiniowana, jak wyjaśniono w tym (częściowo nieaktualnym) linku . Ustawienie właściwej kategorii jest ważne, między innymi, aby ustawić wskaźnik w odpowiedniej pozycji w panelu.
Główne wyzwanie; jak zaktualizować tekst wskaźnika i / lub ikonę
Prawdziwe wyzwanie nie polega na tym, jak napisać podstawowy wskaźnik, ale jak okresowo aktualizować tekst i / lub ikonę wskaźnika, ponieważ chcesz, aby pokazywał (tekstowy) czas. Aby wskaźnik działał poprawnie, nie możemy po prostu threading
rozpocząć drugiego procesu okresowej aktualizacji interfejsu. Cóż, właściwie możemy, ale na dłuższą metę doprowadzi to do konfliktów, jak się dowiedziałem.
Oto, gdzie GObject
przychodzi, do, jak to jest umieszczone w tym (również nieaktualnym) linku :
wywołanie gobject.threads_init()
przy inicjalizacji aplikacji. Następnie uruchamiasz wątki normalnie, ale upewnij się, że wątki nigdy nie wykonują bezpośrednio żadnych zadań GUI. Zamiast tego używasz gobject.idle_add
planowania zadania GUI do wykonania w głównym wątku
Kiedy możemy zastąpić gobject.threads_init()
przez GObject.threads_init()
i gobject.idle_add
przez GObject.idle_add()
, dość dużo mają zaktualizowaną wersję, jak uruchomić wątki w Gtk
aplikacji. Uproszczony przykład pokazujący rosnącą liczbę małp:
#!/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()
To jest zasada. W rzeczywistym wskaźniku w tej odpowiedzi zarówno czas pętli, jak i tekst wskaźnika zostały określone przez dodatkowy moduł zaimportowany do skryptu, ale główna idea jest taka sama.