TITLE:SystemTrayにアイコンを表示

Posted by at 2007-03-05

SystemTrayにアイコンを表示

`JDK 6で追加された機能を使って、SystemTray`にアイコンを表示します。

  • &jar;
  • &zip;
SystemTray.png

サンプルコード

public MainPanel(final JFrame frame) {
  super();
  if(!SystemTray.isSupported()) {
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    return;
  }
  frame.addWindowStateListener(new WindowAdapter() {
    @Override public void windowIconified(WindowEvent e) {
      frame.dispose();
    }
  });
  final SystemTray tray = SystemTray.getSystemTray();
  final Image image     = new ImageIcon(
                            getClass().getResource("16x16.png")).getImage();
  final PopupMenu popup = new PopupMenu();
  final TrayIcon icon   = new TrayIcon(image, "TRAY", popup);

  MenuItem item1 = new MenuItem("OPEN");
  item1.addActionListener(new ActionListener() {
    @Override public void actionPerformed(ActionEvent e) {
      frame.setVisible(true);
    }
  });
  MenuItem item2 = new MenuItem("EXIT");
  item2.addActionListener(new ActionListener() {
    @Override public void actionPerformed(ActionEvent e) {
      tray.remove(icon);
      frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      frame.dispose();
      //System.exit(0);
    }
  });
  popup.add(item1);
  popup.add(item2);

  try{
    tray.add(icon);
  }catch(AWTException e) {
    e.printStackTrace();
  }
}
View in GitHub: Java, Kotlin

解説

トレイアイコンでは、`JPopupMenuではなく、PopupMenuMenuItem`を使用します。

上記のサンプルでは、フレームがアイコン化(最小化)されたときにタスクバーの表示を消して、システムトレイにアイコンだけ表示したいので、初期状態を`frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);にしておき、アイコン化された場合でも、frame.dispose();`するようにしています。

実際に`VMを終了する場合は、表示可能なウィンドウをすべて破棄して(frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);)、システムトレイからもtray.remove(icon);`してアイコンを取り除けばいいようです。

参考リンク

コメント

  • `Ubuntu`だと通知スペースに表示されるのですが、背景色や位置がどうもうまくいっていないようです。 -- aterai
    • 位置は以下みたいにすれば適当に補正できそうですが、背景色はどうしたらいいんだろう? `g.setColor(UIManager.getColor("Panel.background"));g.fillRect(0,0,d.width,d.height);`とかするのは酷いか…。 -- aterai
SystemTray tray = SystemTray.getSystemTray();
Dimension d = tray.getTrayIconSize();
//Image image = new ImageIcon(getClass().getResource("16x16.png")).getImage();
BufferedImage image = new BufferedImage(d.width,d.height,BufferedImage.TYPE_INT_ARGB);
ImageIcon i = new ImageIcon(getClass().getResource("16x16.png"));
Graphics g = image.createGraphics();
i.paintIcon(null,g,(d.width-i.getIconWidth())/2,(d.height-i.getIconWidth())/2);
g.dispose();
PopupMenu popup = new PopupMenu();
TrayIcon icon   = new TrayIcon(image, "TRAY", popup);
  • `g.setBackground(new Color(0,0,0,0));g.clearRect(0,0,d.width,d.height);`とかしても変化無し。 -- aterai
  • メモ: TrayIcon does not support 8-bit alpha channel in Windows XP -- aterai
  • タスクバーのアイコンがなくなりシステムトレイのアイコンだけになりませんか? --
    • `Windowsでしか試していませんが、JFrameの代わりに、JDialog`を使えばタスクバーには何も表示されないと思います(質問の意味を取り違えてなければいいのですが……)。 -- aterai
  • 消したいのはタイトルバーではなくてシステムトレイの隣のタスクバーアイコンです。文字で伝えるのは難しいですね。 --
  • スクリーンショットで`JST`システムトレイとタスクバーにあるやつです --
    • `JFrameの代わりに、JDialog` JWindowを使うのはどうでしょうか。 -- aterai
    • もしくは、JFrameのアイコンを非表示のように透明なアイコンを設定する(クリックすると反応してしまいますが…)とか。 -- aterai