Update GTK+ MenuItem Countdown Each Second, and Periodic Function Call

…衆ロ難τιáo~ 提交于 2020-01-15 11:46:25

问题


This is my International Space Station indicator. I am trying to create a GTK MenuItem that displays a countdown. This wil be in an Ubuntu Unity indicator using AppIndicator3. I want this MenuItem (futpass)to refresh each second (i.e., countdown appears in real time), but also want it to stay inactive when the menu is not selected so as to not consume system resources. Problem is, I can't get it to refresh on its own.

Because there is a long wait period between each time checkiss needs to be run, I also need to know the proper approach to calling this function at a set time with minimal CPU wakeups.

Here is my (rough) code so far:

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

回答1:


Use gobject.timeout_add to schedule the callback to happen at regular intervals. For example:

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

The function will be called from the main loop at regular intervals as long as it returns a true value. If you want a one-shot function, simply return False, or allow it to implicitly return None. To schedule a function at a specific point in time, calculate the time between now and that point, and invoke timeout_add with that period.

When the menu is activated, reschedule the function to happen quicker; when deactivated, schedule it slow again. To reschedule the function, call gobject.source_remove with the value returned by gobject.timeout_add, then call timeout_add with the new timeout value.

The gtk main loop will make sure that the process is not woken up unless it receives events, or the timeout expires.



来源:https://stackoverflow.com/questions/14983279/update-gtk-menuitem-countdown-each-second-and-periodic-function-call

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!