Как я могу записать динамично обновленное приложение панели / индикатор?

Я пытаюсь записать некоторые приложения панели для ubuntu Mate. Я знаю C/C++ и SDL обоснованно хорошо. Я видел приложения панели Mate-University страница GitHub, но я не могу заставить ее работать правильно / я имею хотя время с нею.

Я просто задаюсь вопросом, если существует некоторая легкая авеню для записи приложений панели? Я не говорю об использовании средства запуска пользовательского приложения, я хотел бы добавить новую функциональность к панели, но я не уверен как. Учебное руководство или описание о записи приложений панели могло быть действительно полезным.

11
задан 12 April 2016 в 02:15

1 ответ

Начиная с какого, кажется, случай для задавания этого вопроса, уже имеет ответ, я отвечаю на этот вопрос как на расширенное объяснение о том, как это было сделано (в python)

Основной статический индикатор

Так как Помощник Ubuntu, от 15,10, поддерживает индикаторы, нет большого различия между записью индикатора и приложением панели для Помощника. Поэтому эта ссылка является хорошей начальной точкой для основного индикатора в python, использование AppIndicator3 API. Ссылка является хорошим запуском, но не предоставляет информации о том, как показать текст на индикаторе, уже не говоря о том, как обновить текст (или значок). Тем не менее, с несколькими дополнениями, это приводит к основному "кадру" индикатора как ниже. Это покажет значок, текстовую метку и меню:

enter image description here

#!/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, категория определяется, как экс-наструганная в этом (частично устаревший) ссылка. Установка правильной категории важна, a.o. для помещения индикатора в соответствующее положение в панели.

Основная проблема; как обновить текст индикатора и/или значок

Реальная проблема не состоит в том, как записать основной индикатор, а как периодически обновлять текст и/или значок Вашего индикатора, так как Вы хотите иметь его, показывают (текстовое) время. Чтобы заставить индикатор работать правильно, мы не можем просто использовать threading запустить второй процесс для периодического обновления интерфейса. Ну, на самом деле мы можем, но на долгосрочной перспективе, это приведет к конфликтам, как я узнал.

Вот то, где GObject входит, к, поскольку это помещается в это (также устаревший) ссылка:

звонить gobject.threads_init() при applicaiton инициализации. Затем Вы обычно запускаете свои потоки, но удостоверяетесь, что потоки никогда не делают задач GUI непосредственно. Вместо этого Вы используете gobject.idle_add запланировать задачу GUI к выполняемому в основном потоке

Когда мы заменяем gobject.threads_init() GObject.threads_init() и gobject.idle_add GObject.idle_add(), у нас в значительной степени есть обновленная версия того, как выполнить потоки в a Gtk приложение. Упрощенный пример, показывая растущее число Обезьян:

enter image description here

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

Это - принцип. В фактическом индикаторе в этом ответе и время цикла и текст индикатора были определены вторичным модулем, импортированным в сценарии, но основная идея является тем же.

15
ответ дан 23 November 2019 в 04:01

Другие вопросы по тегам:

Похожие вопросы: