Оскільки на те, що, здається, є приводом задати це питання, вже є відповідь , я відповідаю на це питання як розширене пояснення того, як це робилося (в python
)
Основний статичний показник
Оскільки Ubuntu Mate з 15,10 підтримує індикатори, між написанням індикатора та панельним додатком для Mate немає великої різниці. Тому це посилання є хорошою відправною точкою для базового показника python
, використовуючи AppIndicator3
API. Посилання є приємним початком, але не дає ніякої інформації про те, як відобразити текст на індикаторі, не кажучи вже про те, як оновити текст (або значок). Тим не менш, з кількома доповненнями, це призводить до базового "кадру" індикатора, як показано нижче. На ньому буде показано піктограму, текстову мітку та меню:
#!/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()
У рядку AppIndicator3.IndicatorCategory.OTHER
категорія визначається, як пояснено у цьому (частково застарілому) посиланні . Встановлення потрібної категорії важливо, а.о., щоб поставити індикатор у відповідне положення на панелі.
Основний виклик; як оновити текст індикатора та / або значок
Справжня задача полягає не в тому, як написати основний показник, а як періодично оновлювати текст та / або піктограму вашого індикатора, оскільки ви хочете, щоб він відображав (текстовий) час. Щоб індикатор працював належним чином, ми не можемо просто використовувати threading
для запуску другого процесу періодичне оновлення інтерфейсу. Ну, насправді ми можемо, але в більш тривалому періоді це призведе до конфліктів, як я з'ясував.
Ось, куди GObject
входить, щоб, як зазначено в цьому (також застарілому) посиланні :
виклик gobject.threads_init()
при ініціалізації програми. Тоді ви запускаєте свої потоки нормально, але переконайтеся, що потоки ніколи не виконують жодних завдань GUI безпосередньо. Замість цього ви використовуєте gobject.idle_add
для планування завдання графічного інтерфейсу, що виконується в основному потоці
Коли ми замінимо gobject.threads_init()
на GObject.threads_init()
і gobject.idle_add
на GObject.idle_add()
, ми в значній мірі маємо оновлену версію про те , як запускати потоки в Gtk
додатку. Спрощений приклад, що показує все більшу кількість Мавп:
#!/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()
Це принцип. В реальному показнику в цій відповіді і час циклу, і текст індикатора визначалися вторинним модулем, імпортованим у сценарій, але головна думка однакова.