【问题标题】:Tray icon application in Python, icon is gonePython中的托盘图标应用程序,图标不见了
【发布时间】:2016-03-14 07:47:03
【问题描述】:

我用 Python 为自己开发了一个小小的壁纸更改应用程序。它在通知托盘中制作了一个图标,可用于根据周围的人在“nice”和“naughty”之间切换模式:P并强制更换壁纸。如果不理会,它仍然每 10 分钟更改一次随机壁纸,从我不断添加到的充满图像的目录中随机选择。一切都很好,直到我从 Ubuntu 14.04“Trusty”升级到 Ubuntu 15.10“Wily”。现在,该应用程序仍然运行,并且会按照应有的方式每 10 分钟更换一次壁纸,但图标不见了。它在托盘中为图标创建了一个 空格,但图标不再出现在其中,空格也不会响应任何鼠标左键或右键单击(左键单击用于强制更改壁纸,右键单击用于给我两种模式的菜单)。运行应用程序时,控制台上不会出现警告或错误消息。我对 Python 不太熟悉,也不知道到底是什么问题。以下是小程序的(非常短的)代码。对不起,如果代码中有任何糟糕的做法,就像我说我真的不是一个 python 人,这似乎是做我想做的最简单的方法,所以我去了。如果有人能帮我解决问题,我将不胜感激!

PS "./change_wall" 只是一个 bash 脚本,除了改变壁纸之外,它还可以做一些其他的事情。我知道问题不存在,因为自动壁纸更改仍在工作,只是 FUBAR 的托盘图标/控制界面。

#!/usr/bin/python

import os
import wx

import time
import thread

class TaskBarIcon(wx.TaskBarIcon):
    def __init__(self):
        super(TaskBarIcon, self).__init__()
        os.chdir("/home/caleb/walls")
        self.SetIcon(wx.Icon('walls.xpm', wx.BITMAP_TYPE_XPM), "Wallpaper switcher")
        self.set_nice(None)
        self.Bind(wx.EVT_TASKBAR_LEFT_UP, self.set_new_wall_x)

    def CreatePopupMenu(self):
        menu = wx.Menu()
        nice_item    = menu.AppendRadioItem(-1, "Nice")
        naughty_item = menu.AppendRadioItem(-1, "Naughty")
        if self.type == 'nice':
            nice_item.Check()
        elif self.type == 'naughty':
            naughty_item.Check()
        menu.Bind(wx.EVT_MENU, self.set_nice, nice_item)
        menu.Bind(wx.EVT_MENU, self.set_naughty, naughty_item)
        return menu

    def set_nice(self, event):
        self.type = 'nice'
        self.set_new_wall()

    def set_naughty(self, event):
        self.type = 'naughty'
        self.set_new_wall()

    def set_new_wall(self):
        os.system("./change_wall " + self.type)
        self.last_changed_time = time.time()

    def set_new_wall_x(self, event):
        self.set_new_wall()

def main():
    app = wx.App(False)
    the_icon = TaskBarIcon()
    thread.start_new_thread(app.MainLoop, ())
    while 1:
        if (time.time() > the_icon.last_changed_time + 600):
            the_icon.set_new_wall()

if __name__ == '__main__':
    main()

【问题讨论】:

  • 刚开始的2个想法,1你python版本改了吗?和 2 您是否测试过使用其他图像作为图标?您的代码正在使用 Mint 17.2

标签: python wxpython trayicon


【解决方案1】:

除了检查我评论中的内容,看看这段代码是否有效,使用的图标应该存在于你的机器上。

import wx

TRAY_TOOLTIP = 'System Tray Demo'
TRAY_ICON = '/usr/share/icons/gnome/16x16/emotes/face-cool.png'

def create_menu_item(menu, label, func):
    item = wx.MenuItem(menu, -1, label)
    menu.Bind(wx.EVT_MENU, func, id=item.GetId())
    menu.AppendItem(item)
    return item

class TaskBarIcon(wx.TaskBarIcon):
    def __init__(self):
        wx.TaskBarIcon.__init__(self)
        self.set_icon(TRAY_ICON)
        self.Bind(wx.EVT_TASKBAR_LEFT_DOWN, self.on_left_down)
        self.Bind(wx.EVT_TASKBAR_RIGHT_DOWN, self.on_right_down)

    def CreatePopupMenu(self):
        menu = wx.Menu()
        create_menu_item(menu, 'Say Hello', self.on_hello)
        menu.AppendSeparator()
        create_menu_item(menu, 'Exit', self.on_exit)
        return menu

    def set_icon(self, path):
        icon = wx.IconFromBitmap(wx.Bitmap(path))
        self.SetIcon(icon, TRAY_TOOLTIP)

    def on_left_down(self, event):
        print 'Tray icon was left-clicked.'

    def on_right_down(self, event):
        print 'Tray icon was right-clicked.'
        event.Skip()

    def on_hello(self, event):
        print 'Hello, world!'

    def on_exit(self, event):
        wx.CallAfter(self.Destroy)

def main():
    app = wx.App()
    TaskBarIcon()
    app.MainLoop()

if __name__ == '__main__':
    main()

【讨论】:

  • 感谢您的回复。我不确定我之前使用的是哪个 Python 版本,但截至目前,'python -V' 报告 2.7.10。我尝试使用另一个具有相同结果的图标。回复:你的代码,我在那个地方没有那个图标,所以我把它改成了下面的,也是一个 16x16 PNG,它确实存在于我的系统上:'/usr/share/icons/Adwaita/16x16/status/ battery-full-charged.png' 但是,当我运行代码时,什么也没有发生。我没有托盘图标,根本没有控制台输出,并且执行一开始就停止。 'ps aux' 告诉我没有与脚本相关的进程仍在运行...
  • 讨厌!运行python,import wx,然后输入wx__version__,它会告诉你你有什么版本的wxpython。如果是 3,您将不得不阅读 Project Phoenix 手册。我假设您正在从命令行运行它,如果没有,请这样做。可能是您的新操作系统缺少某些东西。
  • wx__version__ 不起作用(NameError: name 'wx__version__' is not defined),但 'print wx.version()' 报告“3.0.2.0 gtk2 (classic)”。我将查看 Project Phoenix 手册。谢谢!
【解决方案2】:

好吧,与其继续使用 wxPython 和这个 Project Phoenix 废话,我已经转而只使用 PyGTK,我不得不说,总的来说,我更喜欢这个。我的代码现在的行为完全符合我的要求,如下所示:

#!/usr/bin/python

import gobject
import gtk
import os
import thread
import time 

last_changed_time = 0
mode = "nice"

def set_mode (new_mode):
  global mode
  mode = new_mode
  change_wall()

def make_menu(event_button, event_time, data=None):
  menu = gtk.Menu()
  nice_item = gtk.CheckMenuItem("Nice")
  naughty_item = gtk.CheckMenuItem("Naughty")
  kill_item = gtk.MenuItem("Quit")
  if mode == "nice":
    nice_item.set_active(True)
  if mode == "naughty":
    naughty_item.set_active(True)
  menu.append(nice_item)
  menu.append(naughty_item)
  menu.append(kill_item)
  nice_item.connect_object("activate", set_mode, ("nice"))
  naughty_item.connect_object("activate", set_mode, ("naughty"))
  kill_item.connect_object("activate", gtk.main_quit, ())
  nice_item.show()
  naughty_item.show()
  kill_item.show()
  menu.popup(None, None, None, event_button, event_time)

def change_wall():
  global last_changed_time
  os.system("./change_wall " + mode)
  last_changed_time = time.time()

def on_right_click(data, event_button, event_time):
  make_menu(event_button, event_time)

def on_left_click(event):
  change_wall()

def auto_update():
  while 1:
    time.sleep(1)
    if time.time() > last_changed_time + 600:
      change_wall()

if __name__ == '__main__':
  gobject.threads_init()
  os.chdir("/home/caleb/walls")
  icon = gtk.status_icon_new_from_file("walls.xpm")
  icon.connect('popup-menu', on_right_click)
  icon.connect('activate', on_left_click)
  change_wall()
  thread.start_new_thread(auto_update, ())
  gtk.main()

我必须在每次检查之前插入 time.sleep(1) 调用以查看是否需要自动更新,以防止图标/菜单本身变得相当滞后。我在使用 wx 时从未遇到过这个问题;有没有更优雅的方法来解决这个问题?

再次感谢您的帮助!

【讨论】:

  • 你可以只加载一个以前版本的 wx 并且你的原始代码会起作用,而不是从一个新的 UI 开始
【解决方案3】:

由于您正在运行 wx.python 3,因此您似乎需要更改一些调用:
IconFromBitmap 变为 Icon
TaskBarIcon 变为 adv.TaskBarIcon
可能还有其他一些细微的差异,但这些似乎是显而易见的。

编辑:
另一个选项是加载以前版本的 wxpython。
为此,您可以像这样在导入中使用wxversion

import wxversion
wxversion.select("2.8-gtk2-unicode")
import wx

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多