Come posso scrivere un'app / indicatore del pannello aggiornato dinamicamente?


12

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 / Mi sto divertendo.

Mi sto solo chiedendo, se c'è qualche strada facile per scrivere le app del pannello? Non sto parlando dell'utilizzo del programma di avvio dell'applicazione personalizzato, vorrei aggiungere nuove funzionalità al pannello, ma non sono sicuro di come. Un tutorial o una descrizione sulla scrittura di app del pannello potrebbero essere davvero utili.

Risposte:


16

Poiché quella che sembra essere l'occasione per porre questa domanda ha già una risposta , rispondo a questa domanda come una spiegazione estesa su come è stata fatta (in python)

Indicatore statico di base

Poiché Ubuntu Mate, dalle 15,10, supporta gli indicatori, non c'è molta differenza tra la scrittura di un indicatore e un'app pannello per Mate. Pertanto, questo collegamento è un buon punto di partenza per un indicatore di base python, utilizzando l' AppIndicator3API. Il collegamento è un buon inizio, ma non fornisce alcuna informazione su come mostrare il testo sull'indicatore, figuriamoci su come aggiornare il testo (o l'icona). Tuttavia, con alcune aggiunte, questo porta ad un "frame" di base di un indicatore come di seguito. Mostrerà un'icona, un'etichetta di testo e un menu:

inserisci qui la descrizione dell'immagine

#!/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()

Nella riga AppIndicator3.IndicatorCategory.OTHER, viene definita la categoria, come spiegato in questo collegamento (parzialmente obsoleto) . È importante impostare la giusta categoria, anche per mettere l'indicatore in una posizione appropriata nel pannello.

La sfida principale; come aggiornare il testo dell'indicatore e / o l'icona

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 il tempo (testuale). Per far funzionare correttamente l'indicatore, non possiamo semplicemente usare threadingper avviare un secondo processo per aggiornare periodicamente l'interfaccia. Bene, in realtà possiamo, ma a lungo termine, porterà a conflitti, come ho scoperto.

Ecco dove GObjectentra, a, come viene inserito in questo link (anche obsoleto) :

chiamare gobject.threads_init()all'inizializzazione dell'applicazione. Quindi avvii i thread normalmente, ma assicurati che i thread non eseguano direttamente alcuna attività della GUI. Invece, si utilizza gobject.idle_addper pianificare l'attività della GUI da eseguire nel thread principale

Quando sostituiamo gobject.threads_init() da GObject.threads_init()e gobject.idle_addper GObject.idle_add(), abbiamo praticamente abbiamo la versione aggiornata di come eseguire thread in un Gtkapplicazione. Un esempio semplificato, che mostra un numero crescente di scimmie:

inserisci qui la descrizione dell'immagine

#!/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()

Questo è il principio. Nell'indicatore reale 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.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.