使用透明背景图像的Java系统托盘图标

23
我使用以下代码在Windows和Linux中设置托盘图标。它在Windows中运行得很好,在Linux中效果还可以。在Linux(Ubuntu)中,我将面板设置为(有点)透明,当我添加一个具有透明背景的GIF时,图标的背景会变成灰色且难看(见图片,绿色钻石“!”)...有什么办法让我添加的GIF图像“保留”其透明背景吗?
图片如下: alt text http://unarm.org/stackoverflow/panel_task.jpg 如果你想测试一下,这是我使用的图像: alt text http://unarm.org/stackoverflow/green_info.gif
import java.awt.*;
import java.awt.event.*;

public class TrayFun {


  static class ShowMessageListener implements ActionListener {
    TrayIcon trayIcon;
    String title;
    String message;
    TrayIcon.MessageType messageType;
    ShowMessageListener(
        TrayIcon trayIcon,
        String title,
        String message,
        TrayIcon.MessageType messageType) {
      this.trayIcon = trayIcon;
      this.title = title;
      this.message = message;
      this.messageType = messageType;
    }
    public void actionPerformed(ActionEvent e) {
      trayIcon.displayMessage(title, message, messageType);
    }
  }

  public static void main(String args[]) {
    Runnable runner = new Runnable() {
      public void run() {
        if (SystemTray.isSupported()) {
          final SystemTray tray = SystemTray.getSystemTray();
          Image image = Toolkit.getDefaultToolkit().getImage("green_info.png");
          PopupMenu popup = new PopupMenu();
          final TrayIcon trayIcon = new TrayIcon(image, "The Tip Text", popup);
          trayIcon.setImageAutoSize(true);

          MenuItem item = new MenuItem("Close");
      item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
          tray.remove(trayIcon);
            }
      });
          popup.add(item);
          try {
            tray.add(trayIcon);
          } catch (AWTException e) {
            System.err.println("Can't add to tray");
          }
        } else {
          System.err.println("Tray unavailable");
        }
      }
    };
    EventQueue.invokeLater(runner);
  }
}

我猜你得换成一个方形图标 :( :( 很高兴你觉得系统托盘是你的守护进程应用的好替代品。这个新应用是关于什么的? :) 是个秘密吗? - OscarRyz
问题:当在其他地方显示时,这个图标图片看起来不透明吗?例如网页? - OscarRyz
这有点像个秘密,但我计划很快将其作为开源项目发布。在其他任何地方显示图像都没问题。你可以看到我已将任务栏图像嵌入下面的代码上方。 - Jack
6个回答

17

问题出在sun.awt.X11.XTrayIconPeer.IconCanvas.paint()方法上!

在绘制之前,图标的背景被粗糙地清除,只是简单地绘制了一个IconCanvas的背景颜色的矩形,以便进行图像动画。

public void paint(Graphics g) {
    if (g != null && curW > 0 && curH > 0) {
        BufferedImage bufImage = new BufferedImage(curW, curH, BufferedImage.TYPE_INT_ARGB);
        Graphics2D gr = bufImage.createGraphics();
        if (gr != null) {
            try {
                gr.setColor(getBackground());
                gr.fillRect(0, 0, curW, curH);
                gr.drawImage(image, 0, 0, curW, curH, observer);
                gr.dispose();

                g.drawImage(bufImage, 0, 0, curW, curH, null);
            } finally {
                gr.dispose();
            }
        }
    }
}

参见:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6453521


10

我注意到这个GitHub仓库自2011年以来并没有太多的活动。这仍然是一个可行的解决方案吗?我在这里记录了一些其他平台托盘问题:http://stackoverflow.com/a/35919788/3196753。拥有一个可靠的、跨平台的解决方案会很好。 - tresf
在某些语言生态系统中(例如Erlang、Haskell和Clojure领域),缺乏活动和问题的开放意味着一开始就没有出现问题。我寻找已经存在并且问题数量逐渐减少,理想情况下是零的库。 - Petrus Theron

2
很可能这个问题无法解决。这取决于Java在Linux中创建托盘子窗口是否做得好。如果Java做错了,当图像被绘制时透明度已经丢失。
以下是需要翻译的内容:
  1. 您正在使用的图标的真实背景值是什么?它是否是上面显示的灰色调?将其设置为紫色,以查看是否使用了图像的透明度(Java默认为灰色背景)。

  2. 确保尝试了PNG的两种透明选项:透明颜色索引和Alpha通道。Alpha通道在Linux中非常普遍,在Windows世界中则不是。

  3. 您的图标分辨率太小了。请使用64x64或更好的128x128。据我所知,托盘图标没有标准分辨率,即使有,也肯定不是16x16。

  4. 您可以尝试的另一种格式是SVG。在确定图像的透明度是问题后再尝试(见1)。

请参阅此处以获取有关此问题的背景信息:http://www.rasterman.com/index.php?page=News(向下滚动到2006年2月2日)。

1)它是透明的(棋盘格背景)...我试着把它变成紫色,托盘里显示为紫色。 2)我在GIMP中保存时尝试了所有不同的PNG选项,但它们都有相同的结果。 3)我还尝试了不同大小的图标,但结果相同。 4)我尝试了SVG...但全部显示为灰色。 - Jack
抱歉,空间不足了。感谢您的想法。您还有其他的想法吗? - Jack
1
所以如果Java实际上无法理解图像的透明度,那真的很奇怪。也许尝试在应用程序内部绘制图像。或者也许有针对这些图像的特定选项。我不知道还能做什么(也许除了SystemTray之外还有其他API可用?) - ypnos

1

0

不是因为这个……而是因为它使用了默认的GNOME主题来渲染透明度 - 这与图像本身无关 - 这是Adobe Air / GNOME之间的冲突 - 如果您切换到一个默认背景为灰色的GNOME主题,那么它将是灰色而不是白色。它使用系统默认图像,因此即使为面板设置了BG图像以使其看起来像Vista一样光滑,它也会这样做。 Adobe Air / Java不知道您已经覆盖了透明度的主题默认值,因此它正在使用系统默认值


我刚刚测试了这个“理论”,它的确是真的。 - freshfitteds

0
你尝试过将它转换为 .PNG 格式(带透明度)吗?我发现 Java 对它们的支持更好(根据我的经验)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接