Dinamik olarak güncellenen bir panel uygulamasını / göstergesini nasıl yazabilirim?


12

Ubuntu Mate için bazı panel uygulamaları yazmaya çalışıyorum. C / C ++ ve SDL'yi gayet iyi biliyorum. Mate-Üniversitesi panel uygulamaları github sayfasını gördüm, ancak düzgün çalışmasını sağlayamıyorum / onunla bir zaman geçiriyorum.

Merak ediyorum, panel uygulamaları yazmak için kolay bir yol varsa? Özel uygulama başlatıcıyı kullanmaktan bahsetmiyorum, panele yeni işlevsellik eklemek istiyorum, ancak nasıl yapılacağından emin değilim. Panel uygulamaları yazma hakkında bir eğitici veya açıklama gerçekten yardımcı olabilir.

Yanıtlar:


16

Bu soruyu sorma vesilesinin zaten bir cevabı olduğundan , bu soruyu nasıl yapıldığına dair geniş bir açıklama olarak cevaplıyorum (in python)

Temel statik gösterge

Ubuntu Mate, 15,10'dan itibaren göstergeleri desteklediğinden, bir gösterge yazmak ve Mate için bir panel uygulaması arasında çok fazla fark yoktur. Bu nedenle, bu bağlantı , API pythonkullanarak temel bir gösterge için iyi bir başlangıç ​​noktasıdır AppIndicator3. Bağlantı güzel bir başlangıçtır, ancak metnin (veya simgenin) nasıl güncelleneceğini , göstergede metnin nasıl gösterileceği hakkında herhangi bir bilgi sağlamaz . Bununla birlikte, birkaç ilavelerle, bu, aşağıdaki gibi bir göstergenin temel bir "çerçevesine" yol açar. Bir simge, bir metin etiketi ve bir menü gösterecektir:

resim açıklamasını buraya girin

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

Satırda AppIndicator3.IndicatorCategory.OTHER, bu (kısmen modası geçmiş) bağlantıda açıklandığı gibi kategori tanımlanır . Doğru kategorinin ayarlanması önemlidir, ao göstergeyi panelde uygun bir konuma getirmek için.

Ana zorluk; gösterge metnini ve / veya simgesini güncelleme

Asıl zorluk, temel bir göstergenin nasıl yazılacağı değil, göstergenizin metnini ve / veya simgesini periyodik olarak nasıl güncelleyeceğinizdir , çünkü (metinsel) zamanı göstermesini istersiniz. Göstergenin düzgün çalışması threadingiçin, arayüzü periyodik olarak güncellemek üzere ikinci bir işlem başlatmak için kullanamayız . Aslında yapabiliriz, ancak daha uzun vadede öğrendiğim gibi çatışmalara yol açacaktır.

İşte burada GObjecto konur olarak, şunları geliyor bu (aynı zamanda modası geçmiş) linkte :

gobject.threads_init()başvurunun başlatılmasında çağrı . Ardından, iş parçacıklarınızı normal olarak başlatırsınız, ancak iş parçacıklarının hiçbir zaman doğrudan GUI görevleri yapmadığından emin olun. Bunun yerine, gobject.idle_addana iş parçacığında yürütülen GUI görevini zamanlamak için kullanın

Biz değiştirdiğinizde gobject.threads_init() tarafından GObject.threads_init()ve gobject.idle_addtarafından GObject.idle_add(), biz hemen hemen bir iş parçacığı çalıştırmak için nasıl güncel sürümüne sahip Gtkbir uygulama. Artan sayıda Maymun gösteren basitleştirilmiş bir örnek:

resim açıklamasını buraya girin

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

İlke bu. Gerçek göstergesi olarak bu cevap , döngü süresi ve gösterge metin hem komut ithal ikincil modül tarafından belirlendi, ancak ana fikri aynıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.