web-dev-qa-db-ja.com

動的に更新されるパネルアプリ/インジケーターを作成するにはどうすればよいですか?

Ubuntu Mate用のパネルアプリをいくつか作成しようとしています。私はC/C++とSDLをかなりよく知っています。 Mate-Universityパネルアプリのgithubページを見てきましたが、正しく動作させることができません。

パネルアプリを作成するための簡単な方法があるかどうか疑問に思っています。カスタムアプリケーションランチャーの使用については説明していません。パネルに新しい機能を追加したいのですが、方法はわかりません。パネルアプリの作成に関するチュートリアルまたは説明は、非常に役立ちます。

10
j0h

すでにこの質問をする機会であると思われるもの 回答がある であるため、私はこの質問にそれがどのように行われたかについての拡張説明として回答しています(python

基本staticインジケーター

15,10のUbuntu Mateはインジケーターをサポートしているため、Mateのインジケーターとパネルアプリの作成に大きな違いはありません。したがって、 このリンク は、AppIndicator3 AP​​Iを使用して、pythonの基本的なインジケーターの適切な開始点です。リンクはナイススタートですが、インジケーターにテキストを表示する方法に関する情報は提供しません。テキスト(またはアイコン)をupdate )。それにもかかわらず、いくつかの追加により、これはインディケータの基本的な「フレーム」を以下のように導きます。アイコン、テキストラベル、メニューが表示されます。

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行では、 この(部分的に古い)リンク で説明されているように、カテゴリが定義されています。適切なカテゴリを設定することは重要です。パネルの適切な位置にインジケータを配置します。

主な課題;インジケーターのテキストやアイコンを更新する方法

本当の課題は、基本的なインジケーターの書き方ではなく、インジケーターのテキストやアイコンを定期的にupdateする方法です。 (テキスト)時間を表示します。インジケーターを適切に機能させるために、単にthreadingを使用して2番目のプロセスを開始し、定期的にインターフェイスを更新することはできません。まあ、実際にはできますが、長い目で見れば、競合につながります。

ここにGObjectが入る場所があります。これは、 この(古い)リンクでも であるためです。

アプリケーションの初期化時にgobject.threads_init()を呼び出します。次に、通常どおりスレッドを起動しますが、スレッドがGUIタスクを直接実行しないようにします。代わりに、gobject.idle_addを使用してGUIタスクをメインスレッドで実行するようにスケジュールします

gobject.threads_init()GObject.threads_init()で、gobject.idle_addGObject.idle_add()で置き換えると、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()

それが原則です。 this answer の実際のインジケーターでは、ループ時間とインジケーターテキストの両方が、スクリプトにインポートされたセカンダリモジュールによって決定されましたが、主な考え方は同じです。

14
Jacob Vlijm