5

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

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

4

3 回答 3

3

我发现YAD(Yet Another Dialog)提供了最简单的解决方案。请参阅webupd8 的简短描述。但是,目前与 Unity 的集成似乎有点中断。我在下面提到了一个解决方法,但如果你真的关心 Unity,你可能应该看看其他答案。

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

安装

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

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按预期工作。(此外,“systemtray”显示了一些我之前一直在徒劳搜索的其他图标。)面板上图标的位置可以通过以下方式进行调整:

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 来结束演示。

于 2015-12-04T21:48:51.407 回答
2

一种简单的方法是用 Python 制作。例如,请参阅此博客文章

于 2009-11-18T16:12:00.073 回答
0

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

#!/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 中的错误而被破坏。有关可能的解决方法,请参阅此答案

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

于 2015-12-12T12:03:39.903 回答