Java TrayIcon, используя изображение с прозрачным фоном - PullRequest
22 голосов
/ 01 декабря 2008

Я использую следующий код для установки иконки в трее в Windows и Linux. Он прекрасно работает в Windows и нормально работает в Linux. В Linux (Ubuntu) моя панель настроена (несколько) прозрачной, и когда я добавляю GIF (с прозрачным фоном), фон значка отображается серым и уродливым (см. Изображение, зеленый ромб "!"). ... Есть идеи, как сделать изображение GIF, которое я добавляю, "сохранить" его прозрачный фон?

альтернативный текст http://unarm.org/stackoverflow/panel_task.jpg

и изображение, которое я использую, если вы хотите проверить:

альтернативный текст 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);
  }
}

Ответы [ 6 ]

17 голосов
/ 07 октября 2010

Проблема заключается в методе 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 голосов
/ 24 мая 2011

Для тех, кто ищет «настоящее» решение, я разработал небольшую библиотеку, которая способна отображать значок в трее с учетом прозрачности, а также принимает значки SVG (для всех платформ):

http://skype2gmail.blogspot.com/2011/05/java-tray-icon-transparency.html

Это библиотека с открытым исходным кодом, и исходный код можно найти здесь:

https://github.com/taksan/native-tray-adapter

Библиотека обходит проблему, предоставляя альтернативу JNI (с GTK) при работе под Linux.

2 голосов
/ 01 декабря 2008

Скорее всего, эта проблема не может быть решена. Это зависит от того, хорошо ли работает Java в создании подокна в Linux или нет. Если Jave делает это неправильно, прозрачность уже теряется при рисовании изображения.

  1. Каково реальное фоновое значение иконки, которую вы используете? Это серый тон, показанный выше? Установите его на фиолетовый, чтобы увидеть, используется ли прозрачность изображения (Java по умолчанию имеет серый фон) или нет.

  2. Убедитесь, что вы опробовали оба варианта прозрачности PNG: индекс прозрачного цвета, а также альфа-канал. Альфа-канал очень распространен в Linux, но не так в мире Windows.

  3. Разрешение вашей иконки слишком мало. Сделайте это в 64x64 или лучше 128x128. AFAIK нет стандартного разрешения для значков в трее, и даже если это так, оно определенно не 16x16.

  4. Другой формат, который вы можете попробовать, это SVG. Попробуйте только после того, как убедитесь, что проблема заключается в прозрачности изображения (см. 1).

Смотрите здесь дополнительную информацию по этому вопросу: http://www.rasterman.com/index.php?page=News (прокрутите вниз до 2 февраля 2006 г.)

1 голос
/ 02 декабря 2008

У JDIC есть иконка в трее, они могут поддерживать прозрачность в Linux ... https://jdic.dev.java.net/

0 голосов
/ 21 апреля 2010

это не то. , , это происходит потому, что для рендеринга прозрачности используется тема GNOME по умолчанию - она ​​не имеет никакого отношения к самому изображению - это конфликт Adobe Air / GNOME - если вы переключитесь на тему GNOME, если фон по умолчанию серый, тогда это было бы серым вместо белого. Он использует системное изображение по умолчанию, поэтому, даже если он был установлен, но тема для панели должна иметь BG-изображение, чтобы оно выглядело, например, как глянцевый, как vista, чем это было бы. Adobe Air / Java не знает, что вы переопределяете тему по умолчанию прозрачностью, и поэтому она использует системную настройку по умолчанию

0 голосов
/ 01 декабря 2008

Вы пытались вместо этого преобразовать его в формат .PNG (с прозрачностью)? Я обнаружил, что они, как правило, лучше поддерживаются Java (по моему опыту)

...