У меня есть индикатор приложения, который показывает фазу / ориентацию луны в виде значка (вместе с текстовой меткой). Когда индикатор выполняет обновление (несколько раз в час), значок воссоздается (как файл SVG), и поэтому значок меняется со временем.
В последнее время значок не показывает никаких изменений, если я не щелкну мышью по значку (или метке). Я нахожусь на Ubuntu 14.04 64 бит, и мой индикатор использует Python 3 и Appindicator3.
Приведенный ниже код представляет проблему и показывает значок, который должен меняться каждые три секунды (я сделал интервал три секунды, чтобы быстро увидеть проблему - на самом деле значок меняется ежечасно максимум). Сам значок представляет собой файл SVG и показывает числовой отсчет, начиная с нуля и увеличиваясь каждые три секунды.
Я провел тестирование на Ubuntu 12.04 и Xubuntu 12.04 (через VirtualBox), и значок ДЕЙСТВИТЕЛЬНО меняется при каждом трехсекундном обновлении.
Во время тестирования в Ubuntu 14.04 значок НЕ меняется, если я не нажму на него. Если я меняю текст метки при каждом обновлении, значок БУДЕТ также меняться, но только если я не повторяю ЖЕ текст для метки.
Кто-нибудь может подтвердить это, пожалуйста? Я не могу найти отчет об ошибке, и API для Python AppIndicator больше не доступен, поэтому я не могу сказать, изменилось ли что-то или устарело.
#!/usr/bin/env python3
try: from gi.repository import AppIndicator3
except: pass
from gi.repository import GLib, Gtk
import os
class IndicatorTestIcon:
NAME = "indicator-test-icon"
SVG_ICON = "." + NAME
SVG_FILE = os.getenv( "HOME" ) + "/" + SVG_ICON + ".svg"
def __init__( self ):
self.count = 0
self.indicator = AppIndicator3.Indicator.new( IndicatorTestIcon.NAME, "", AppIndicator3.IndicatorCategory.APPLICATION_STATUS )
self.indicator.set_icon_theme_path( os.getenv( "HOME" ) )
self.indicator.set_status( AppIndicator3.IndicatorStatus.ACTIVE )
def main( self ):
self.update()
GLib.timeout_add_seconds( 3, self.update )
Gtk.main()
def update( self ):
self.buildMenu()
self.createIcon()
self.indicator.set_icon( IndicatorTestIcon.SVG_ICON )
# self.indicator.set_label( "static label", "" ) # Using a static label, the icon does not change unless clicked with the mouse.
self.indicator.set_label( str( self.count ), "" ) # Using a dynamic label (which does not repeat) DOES change the icon.
self.count += 1
return True
def buildMenu( self ):
menu = Gtk.Menu()
quitMenuItem = Gtk.ImageMenuItem.new_from_stock( Gtk.STOCK_QUIT, None )
quitMenuItem.connect( "activate", Gtk.main_quit )
menu.append( quitMenuItem )
self.indicator.set_menu( menu )
menu.show_all()
def createIcon( self ):
header = '<?xml version="1.0" standalone="no"?>' \
'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' \
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100">'
text = '<g>' \
'<text x="0" y="75" font-family="Verdana" font-size="100" fill="white" >' + str( self.count ) + '</text>' \
'</g>'
footer = '</svg>'
with open( IndicatorTestIcon.SVG_FILE, "w" ) as f:
f.write( header + text + footer )
f.close()
if __name__ == "__main__": IndicatorTestIcon().main()
К вашему сведению: отправлено сообщение об ошибке https://bugs.launchpad.net/ubuntu/+bug/1337620
После тестирования различных сценариев самое простое обходное решение (кроме самой ошибки, зафиксированной, предполагая, что это - ошибка), должно чередовать именование файла значка назад и вперед...
#!/usr/bin/env python3
from gi.repository import AppIndicator3, GLib, Gtk
import glob, os
class IndicatorTestIcon:
NAME = "indicator-test-icon"
ICON_STATE = True
def __init__( self ):
self.count = 0
for file in glob.glob( os.getenv( "HOME" ) + "/." + IndicatorTestIcon.NAME + "*.svg" ):
print(file)
os.remove( file )
self.indicator = AppIndicator3.Indicator.new( IndicatorTestIcon.NAME, "", AppIndicator3.IndicatorCategory.APPLICATION_STATUS )
self.indicator.set_icon_theme_path( os.getenv( "HOME" ) )
self.indicator.set_status( AppIndicator3.IndicatorStatus.ACTIVE )
def main( self ):
self.update()
GLib.timeout_add_seconds( 3, self.update )
Gtk.main()
def update( self ):
print( self.count )
self.buildMenu()
self.createIcon()
self.indicator.set_label( "static label", "" )
self.indicator.set_icon_full( self.getIconName(), "" )
self.count += 1
self.toggleIconState()
return True
def buildMenu( self ):
menu = Gtk.Menu()
quitMenuItem = Gtk.ImageMenuItem.new_from_stock( Gtk.STOCK_QUIT, None )
quitMenuItem.connect( "activate", Gtk.main_quit )
menu.append( quitMenuItem )
self.indicator.set_menu( menu )
menu.show_all()
def createIcon( self ):
header = '<?xml version="1.0" standalone="no"?>' \
'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' \
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100">'
text = '<g>' \
'<text x="0" y="75" font-family="Verdana" font-size="100" fill="white" >' + str( self.count ) + '</text>' \
'</g>'
footer = '</svg>'
with open( self.getIconFile(), "w" ) as f:
f.write( header + text + footer )
f.close()
def getIconName( self ):
if IndicatorTestIcon.ICON_STATE: return "." + IndicatorTestIcon.NAME + "-1"
return "." + IndicatorTestIcon.NAME + "-2"
def getIconFile( self ):
if IndicatorTestIcon.ICON_STATE: return os.getenv( "HOME" ) + "/." + IndicatorTestIcon.NAME + "-1.svg"
return os.getenv( "HOME" ) + "/." + IndicatorTestIcon.NAME + "-2.svg"
def toggleIconState( self ): IndicatorTestIcon.ICON_STATE = not IndicatorTestIcon.ICON_STATE
if __name__ == "__main__": IndicatorTestIcon().main()
Я думаю, что это разумно как путь темы & имя значка не изменилось не будет никакого обновления/перезагрузки для значка индикатора (почему это должно освободить некоторые циклы для перезагрузки его? Это оптимально, нет?!).
ну, libappindicator
был разработан для статических значков, загруженных из файлов. ( LP bug#812067: API было нужно: поддержка установки значка pixbuf ). Вы хотите сделать обходное решение на этом путем изменения содержания файла значка. В Вашем случае хорошо, но не для общего использования, где этому нужна более короткая задержка обновления (исключая: 120 мс), т.е., слишком много файла io запросы (открытый, пишут, близко).
Также, Вы изменяете путь темы, это - вид приема:
self.indicator.set_icon_theme_path( os.getenv( "HOME" )+"./"*(self.count % 2) )
self.indicator.set_icon_full( IndicatorTestIcon.SVG_ICON, str( self.count ) )
Или меняют имя (можно использовать тот же предыдущий метод, чередующийся между 2 именами):
SVG_ICON = "." + NAME+ "_{0}"
...
self.indicator.set_icon_full( IndicatorTestIcon.SVG_ICON.format(self.count % 2) , str( self.count ) )
...
with open( IndicatorTestIcon.SVG_FILE.format(self.count % 2), "w" ) as f:
BTW, это лучше для использования set_icon_full
, set_icon
удерживается от использования. (Протестированный на Ubuntu 14.04)