【问题标题】:Add a changing icon to Ubuntu Panel向 Ubuntu 面板添加更改图标
【发布时间】:2010-12-17 22:15:18
【问题描述】:

在 Ubuntu (Gnome) 面板中添加和更改图标的最简单方法是什么?我正在寻找像 shell 脚本这样简单的东西,但我不限于此。如果这是一种更好或更简单的方法,将为它编写一个程序。

这个想法是创建一个脚本/程序来监控某些条件(例如,挂载点的可用性、互联网连接的可用性),并更改图标的状态以反映当前状态。

【问题讨论】:

    标签: linux ubuntu panel gnome


    【解决方案1】:

    一种简单的方法是在 Python 中实现。例如,请参阅此blog post

    【讨论】:

    • 如果该示例实际包含在帖子中而不是将其全部保留在外部链接中(现在已死),那就太好了。不幸的是,这个答案现在几乎没用了。 :(
    • “Python 解决方案”在this question 的回复中有详细讨论。
    【解决方案2】:

    我发现YAD (Yet Another Dialog) 提供了最简单的解决方案。见webupd8's short description。但是,目前与 Unity 的集成似乎有点中断。我在下面提到了一种解决方法,但如果您真的关心 Unity,您可能应该查看其他答案。

    注意:虽然我相信 YAD 可以在各种环境中工作,但我只使用 Lubuntu 15.10(LXDE 桌面)和 Ubuntu 14.04(Unity 桌面)测试了以下说明.

    安装

    我获得了一个有效的安装:

    sudo apt-add-repository ppa:webupd8team/y-ppa-manager 
    sudo apt-get update
    sudo apt-get install yad
    

    (事实上,我在 Lubuntu 15.10 中不需要前两行,但这可能是巧合。)
    在 LXDE 中,调用

    yad --notification --listen
    

    然后弹出一个托盘图标,我可以通过输入(例如)来更改它:icon:gtk-help。在 Unity 中,什么都没有出现,所以我需要以下...

    Unity 的解决方法: 以下说明再次取自webupd8。 问题是 Unity 中不再正式存在“系统托盘”。运行 YAD 等尚未赶上此更改的程序的一种可能解决方案是安装“系统托盘模拟器”:

    sudo apt-add-repository ppa:fixnix/indicator-systemtray-unity
    sudo apt-get update
    sudo apt-get install indicator-systemtray-unity
    

    为了直接在 Unity 面板中获取图标,我使用了以下设置:

    gsettings set net.launchpad.indicator.systemtray tray-is-static true
    gsettings set net.launchpad.indicator.systemtray show-background-static false
    

    一旦我退出并重新登录,yad --notification 就会按预期工作。 (此外,“系统托盘”显示了一些我之前一直在徒劳搜索的附加图标。)面板上图标的位置可以通过以下方式调整:

    gsettings set net.launchpad.indicator.systemtray static-x 1500
    

    (其中 1500 可以替换为任何合理的值)。我不知道如何让图标正确显示。如果您想再次卸载“系统托盘模拟器”,webupd8 推荐:

    sudo apt-get purge indicator-systemtray-unity
    

    演示

    这是一个简单的演示,可能有助于说明如何在实际场景中使用 YAD。我假设 YAD 本身已经如上所述安装。假设我们想查看在命令行上运行的某个程序的输出并相应地更新托盘图标。为了这个演示的目的,让我们把这个“程序”当作下面的脚本“dummyprogram.sh”:

    #! /bin/bash
    i=1
    while [ $i -ne 3 ]
    do
      let "i=((i+1)%2)"
    echo $i
      sleep 1
    done
    

    将以上行复制到文件“dummyprogram.sh”,使用“chmod +x dummyprogram.sh”使其可执行并调用“./dummyprogram.sh”应该会产生以下输出:

    0
    1
    0
    1
    ...
    

    (每秒一行)。现在是手头的实际任务。为了在托盘区域获得上述输出的“图标化”版本,我们使用以下脚本“demo.sh”:

    #! /bin/bash
    while read x
    do
      if  [ $x -eq 0 ]
      then
        echo icon:gtk-home
      else
        echo icon:gtk-help
      fi
    done
    

    再次,将这些行复制到文件“demo.sh”并使其可执行。调用

    ./dummyprogram.sh | ./demo.sh | yad --notification --listen
    

    现在应该会产生所需的结果:托盘区域中的图标每秒会在两个不同的图标之间来回变化。

    您可以通过在终端中键入 Ctrl-C 来结束演示。

    【讨论】:

      【解决方案3】:

      对于那些关心 Unity 的人来说,目前可能不存在简单的解决方案。因此,也许编写一个使用 Unity 的 AppIndicator-API 的自定义 Python 脚本确实是要走的路。网络上已经有很多这样的例子,但我仍然花了相当多的努力才得到一个实现与solution using YAD described in my other answer 大致相同功能的脚本:一个将监听程序输出的脚本并相应地更新“托盘图标”。这是我的解决方案:

      #!/usr/bin/python
      import os, threading, signal
      from subprocess import Popen, PIPE, STDOUT
      from gi.repository import Gtk
      from gi.repository import AppIndicator3 as AppIndicator
      
      class my_indicator:
          ICON_0 = "gtk-home" 
          ICON_1 = "gtk-help"       
      
          def __init__(self, wrapper):
              self.ind = AppIndicator.Indicator.new("my-app-indicator", Gtk.STOCK_INFO, AppIndicator.IndicatorCategory.SYSTEM_SERVICES)
              self.ind.set_status(AppIndicator.IndicatorStatus.ACTIVE)
              self.wrapper = wrapper
              self.build_menu()
      
          def build_menu(self):
              item_quit = Gtk.MenuItem('Quit')
              item_quit.connect('activate', self.wrapper.quit)
              menu = Gtk.Menu()
              self.ind.set_menu(menu)
              menu.append(item_quit)
              menu.show_all()
      
          def update_icon(self,icon):
              self.ind.set_icon(icon)
      
      class dummy_wrapper:
          PROGRAM = "./dummyprogram.sh"
      
          def __init__(self):
              self.indicator = my_indicator(self)
      
          def main(self):
              self.process = Popen(self.PROGRAM, stdout=PIPE, stderr=STDOUT, close_fds=True, shell=True, preexec_fn=os.setsid)
              self.thread = threading.Thread(target=self.watch_pipe, args=(self.process.stdout,self.indicator))
              self.thread.daemon = True
              self.thread.start() 
              Gtk.main()
      
          def quit(self, source):
              if self.process:
                  os.killpg(self.process.pid, signal.SIGTERM)               
              if self.thread:
                  self.thread.join() 
              Gtk.main_quit()
      
          @staticmethod
          def watch_pipe(pipe, indicator): 
              while 1:  
                  line = pipe.readline().strip() 
                  # The thread waits here until a line appears in the pipe.
                  if not line: 
                      # This happens exactly once, namely when the process ends.
                      break
                  else:
                      print line
                      if line=="0": 
                          indicator.update_icon(my_indicator.ICON_0)
                      else:
                          indicator.update_icon(my_indicator.ICON_1)  
      
      dummy_wrapper().main()
      

      关于代码的一些简要说明:

      • 调用和关闭我想听的程序的行的语法(./dummyprogram.sh),即self.process = Popen(...的行 和os.killpg(... 取自this answer。这似乎是终止 shell(子)进程的唯一可靠方法。
      • 无法使用 Ctrl-C 终止脚本 - 请改用菜单项“退出”)。应该可以使用信号库为 Ctrl-C 添加事件处理程序,但这似乎由于 Gtk 中的错误而被破坏。请参阅 this answer 了解可能的解决方法。

      演示:将上述代码粘贴到文件my-indicator.py 中,并使用chmod +x my-indicator.py 使其可执行。对my answer proposing YAD 中描述的文件dummy-programm.sh 执行相同的操作。致电./my-indicator.py,您应该会在 Unity 面板中看到一个图标,该图标每秒会在两个不同的图标之间来回切换。 (如果安装了 Ubuntu 的 app-indicator-library,这应该也适用于 gnome 和 KDE 桌面。)

      【讨论】:

        猜你喜欢
        • 2012-02-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多