Snažím se napsat nějaké panelové aplikace pro ubuntu Mate.
Znám C/C++ a SDL poměrně dobře.
Viděl jsem stránku panelových aplikací Mate-University github, ale nemohu ji zprovoznit správně / Mám s tím čas.
Jen by mě zajímalo, jestli existuje nějaká snadná cesta k psaní panelových aplikací? Nemluvím o použití vlastního spouštěče aplikací, rád bych do panelu přidal novou funkcionalitu, ale nejsem si jistý, jak na to. Výukový program nebo popis psaní panelových aplikací může být opravdu užitečný.
Nejlepší odpověď
Vzhledem k tomu, že to, co se zdá být příležitostí položit tuto otázku, již má odpověď, odpovídám na tuto otázku jako rozšířené vysvětlení toho, jak to bylo provedeno (v python
)
Základní statické indikátor
Vzhledem k tomu, že Ubuntu Mate od 15,10 podporuje indikátory, není velký rozdíl mezi psaním indikátoru a panelovou aplikací pro Mate. Proto je tento odkaz dobrým výchozím bodem pro základní indikátor v python
pomocí AppIndicator3
API. Odkaz je pěkný začátek, ale neposkytuje žádné informace o tom, jak zobrazit text na indikátoru, natož jak jej aktualizovat text (nebo ikonu). Nicméně s několika dodatky to vede k základnímu „rámci“ indikátoru, jak je uvedeno níže. Zobrazí se ikona, textový štítek a nabídka:
#!/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()
V řádku AppIndicator3.IndicatorCategory.OTHER
, je kategorie definována, jak je vysvětleno v tomto (částečně zastaralém) odkazu. Nastavení správné kategorie je důležité, a.o. umístěte indikátor na vhodné místo na panelu.
Hlavní výzva; jak aktualizovat text indikátoru a/nebo ikonu
Skutečnou výzvou není, jak napsat základní indikátor, ale jak jej pravidelně aktualizovat text a/nebo ikona vašeho indikátoru, protože chcete, aby zobrazoval (textový) čas. Aby indikátor fungoval správně, nemůžeme jednoduše použít threading
spustit druhý proces pro pravidelnou aktualizaci rozhraní. No, vlastně můžeme, ale z dlouhodobého hlediska to povede ke konfliktům, jak jsem zjistil.
Zde je GObject
přichází, do, jak je uvedeno v tomto (také zastaralém) odkazu:
volání gobject.threads_init()
při inicializaci aplikace. Poté svá vlákna spustíte normálně, ale ujistěte se, že vlákna nikdy neprovádějí přímo žádné úlohy GUI. Místo toho použijete gobject.idle_add
naplánovat provedení úlohy GUI v hlavním vláknu
Když nahradíme gobject.threads_init()
pomocí GObject.threads_init()
a gobject.idle_add
pomocí GObject.idle_add()
, v podstatě máme aktualizovanou verzi, jak spouštět vlákna v Gtk
aplikace. Zjednodušený příklad ukazující rostoucí počet opic:
#!/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()
To je princip. Ve skutečném indikátoru v této odpovědi byly jak doba smyčky, tak text indikátoru určeny sekundárním modulem importovaným do skriptu, ale hlavní myšlenka je stejná.