1

これは私の国際宇宙ステーションのインジケーターです。カウントダウンを表示するGTKMenuItemを作成しようとしています。これは、AppIndicator3を使用するUbuntuUnityインジケーターに含まれます。このMenuItem(futpass)を毎秒更新する(つまり、カウントダウンがリアルタイムで表示される)だけでなく、システムリソースを消費しないように、メニューが選択されていないときに非アクティブのままにしておく必要があります。問題は、それを自分でリフレッシュさせることができないということです。

checkiss実行する必要があるたびに長い待機期間があるため、CPUのウェイクアップを最小限に抑えて、設定された時間にこの関数を呼び出すための適切なアプローチも知っておく必要があります。

これまでの私の(大まかな)コードは次のとおりです。

#!/usr/bin/env python
#print time.localtime( time.time() )
import json, urllib2, time, math

#indicator
from gi.repository import Gtk
from gi.repository import AppIndicator3 as appindicator
class indicator():
    def __init__(self):
        #create indicator
        self.ind = appindicator.Indicator.new (
                        "issindicator",
                        "indicator-messages",
                        #"indicator-messages",
                        appindicator.IndicatorCategory.APPLICATION_STATUS)
        self.ind.set_status (appindicator.IndicatorStatus.ACTIVE)

        self.ind.set_attention_icon ("indicator-messages-new")

        #dropdown menu
        #now items
        self.menu = Gtk.Menu()
        self.curpass = Gtk.MenuItem("not refreshed")
        self.curpass.connect("activate", self.checkiss)
        self.menu.append(self.curpass)

        self.curpassdur = Gtk.MenuItem(" ")
        self.menu.append(self.curpassdur)

        self.curpassrise = Gtk.MenuItem(" ")
        self.menu.append(self.curpassrise)

        self.curpassset = Gtk.MenuItem(" ")
        self.menu.append(self.curpassset)

        self.sep1 = Gtk.SeparatorMenuItem()
        self.menu.append(self.sep1)

        #future items
        self.futpass = Gtk.MenuItem(" ")
        self.menu.append(self.futpass)

        self.sep2 = Gtk.SeparatorMenuItem()
        self.menu.append(self.sep2)

        #Options

        self.aboutmenu = Gtk.MenuItem("About")
        self.aboutmenu.connect("activate", self.onabout)
        self.menu.append(self.aboutmenu)

        self.quit = Gtk.MenuItem("Quit")
        self.quit.connect("activate", self.quitnow)
        self.menu.append(self.quit)

        self.curpass.show()
        self.sep1.show()
        self.futpass.show()
        self.sep2.show()
        self.aboutmenu.show()
        self.quit.show()
        self.ind.set_menu(self.menu)

        #get iss data
        self.updatecache()
        self.checkiss()

        Gtk.main()


    #define code to hide or show icon
    def hideicon(self, w=None):
        self.ind.set_status (appindicator.IndicatorStatus.PASSIVE)

    def showicon(self, w=None):
        self.ind.set_status (appindicator.IndicatorStatus.ACTIVE)

    def quitnow(self, w=None):
        Gtk.main_quit()

    def onabout(self,widget):
        widget.set_sensitive(False)
        ad=Gtk.AboutDialog()
        ad.set_name("aboutdialog")
        ad.set_version("0.1")
        ad.set_copyright('Copyrignt (c) 2013 mh00h')
        ad.set_comments('Indicating ISS Zarya')
        ad.set_license(''+
        'This program is free software: you can redistribute it and/or modify it\n'+
        'under the terms of the GNU General Public License as published by the\n'+
        'Free Software Foundation, either version 3 of the License, or (at your option)\n'+
        'any later version.\n\n'+
        'This program is distributed in the hope that it will be useful, but\n'+
        'WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n'+
        'or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n'+
        'more details.\n\n'+
        'You should have received a copy of the GNU General Public License along with\n'+
        'this program.  If not, see <http://www.gnu.org/licenses/>.')
        ad.set_website('https://launchpad.net/~mh00h/+archive/issindicator')
        ad.set_website_label('ISSIndicator Homepage')
        ad.set_authors(['mh00h'])
        ad.run()
        ad.destroy()
        widget.set_sensitive(True)

    def updatecache(self, w=None):
        self.passingstatus = 'not set yet'
        #get ISS data from api
        self.ip = urllib2.urlopen("http://api.exip.org/?call=ip").read()
        self.geoip = json.load(urllib2.urlopen("http://freegeoip.net/json/"+self.ip))
        self.data = json.load(urllib2.urlopen("http://api.open-notify.org/iss/?lat="+str(self.geoip["latitude"])+"&lon="+str(self.geoip["longitude"])+"&alt=280&n=27"))

    def checkiss(self, w=None):
        self.n = 0
        self.passingstatus = "The ISS is not overhead."

        #check if cache is out of date and update if needed
        if time.time() > self.data['response'][len(self.data['response'])-1]['risetime']:
            self.updatecache
        for k in self.data['response']:
            duration = self.data['response'][self.n]['duration']
            risetime = self.data['response'][self.n]['risetime']
            settime = risetime + duration
            #print risetime, time.time(), settime
            if risetime <= time.time() <= settime:
                self.showicon()
                self.passingstatus = "The ISS is overhead"
                self.curpass.get_child().set_text(self.passingstatus)
                self.curpassdur.get_child().set_text("Duration: "+
                                                     str(time.strftime('%M:%S', time.gmtime(duration)))+" ("+
                                                     str(time.strftime('%M:%S', time.gmtime(time.time()-duration)))+" remaining)")
                self.curpassdur.show()
                self.curpassrise.get_child().set_text("Rise time: "+time.strftime('%H:%M:%S', time.gmtime(risetime)))
                self.curpassrise.show()
                self.curpassset.get_child().set_text("Set time: "+time.strftime('%H:%M:%S', time.gmtime(settime)))
                self.curpassset.show()
                break
            else:
                self.n += 1

        if self.passingstatus != "The ISS is overhead":
            self.curpass.get_child().set_text(self.passingstatus)
            self.curpassdur.hide()
            self.curpassrise.hide()
            self.curpassset.hide()
            #self.hideicon()

        #regardless of isspass, show the next pass time
        if self.n != len(self.data['response']):
            self.futpass.get_child().set_text("Next Pass: "+str(time.strftime('%H:%M:%S', time.gmtime(self.data['response'][self.n]['risetime'])))+" ("+str(time.strftime('%H:%M:%S', time.gmtime(self.data['response'][self.n+1]['risetime']-time.time())))+")")
        else:
            self.futpass.get_child().set_text("Next Pass: "+str(time.strftime('%H:%M:%S', time.gmtime(self.data['response'][0]['risetime'])))+" ("+str(time.strftime('%H:%M:%S', time.gmtime(self.data['response'][0]['risetime']-time.time())))+")")

if __name__ == '__main__':
    issindicator = indicator()
4

1 に答える 1

1

gobject.timeout_addコールバックが定期的に発生するようにスケジュールするために使用します。例えば:

gobject.timeout_add(3600 * 1000, self.checkiss)

関数は、真の値を返す限り、定期的にメインループから呼び出されます。ワンショット関数が必要な場合は、単にを返すFalseか、暗黙的にを返すようにしNoneます。特定の時点で関数をスケジュールするには、現在からその時点までの時間を計算し、timeout_addその期間で呼び出します。

メニューがアクティブになったら、機能をより速く実行するようにスケジュールを変更します。非アクティブ化されたら、再度低速にスケジュールします。関数のスケジュールを変更するには、gobject.source_removeによって返された値を使用してgobject.timeout_add呼び出しtimeout_addてから、新しいタイムアウト値を使用して呼び出します。

gtkメインループは、イベントを受信するか、タイムアウトが期限切れにならない限り、プロセスがウェイクアップされないようにします。

于 2013-02-20T22:58:10.360 に答える