• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:SystemTrayにアイコンを表示
#navi(../)
RIGHT:Posted by [[terai]] at 2007-03-05
*SystemTrayにアイコンを表示 [#n4a8cf0f]
JDK 6 で追加された機能を使って、SystemTrayにアイコンを表示します。
---
category: swing
folder: SystemTray
title: SystemTrayにアイコンを表示
tags: [SystemTray, Icon]
author: aterai
pubdate: 2007-03-05T02:26:31+09:00
description: JDK 6で追加された機能を使って、SystemTrayにアイコンを表示します。
image: https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTUJeisovI/AAAAAAAAAlk/zvAoP96Ntcs/s800/SystemTray.png
---
* 概要 [#summary]
`JDK 6`で追加された機能を使って、`SystemTray`にアイコンを表示します。

//-&jnlp;
-&jar;
-&zip;
#download(https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTUJeisovI/AAAAAAAAAlk/zvAoP96Ntcs/s800/SystemTray.png)

#screenshot

**サンプルコード [#ie1fffe5]
#code{{
* サンプルコード [#sourcecode]
#code(link){{
public MainPanel(final JFrame frame) {
  super();
  if(!SystemTray.isSupported()) {
  if (!SystemTray.isSupported()) {
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    return;
  }
  frame.addWindowStateListener(new WindowAdapter() {
    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);
  SystemTray tray = SystemTray.getSystemTray();
  Image image = new ImageIcon(getClass().getResource("16x16.png")).getImage();
  PopupMenu popup = new PopupMenu();
  TrayIcon icon   = new TrayIcon(image, "TRAY", popup);

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

  try{
  try {
    tray.add(icon);
  }catch(AWTException e) {
  } catch (AWTException e) {
    e.printStackTrace();
  }
}
}}

**解説 [#g1110d96]
トレイアイコンでは、JPopupMenuではなく、PopupMenuやMenuItemを使用します。
* 解説 [#explanation]
- デフォルトの`TrayIcon`では、`JPopupMenu`ではなく`PopupMenu`や`MenuItem`が使用される
- 上記のサンプルでは、フレームがアイコン化(最小化)されたときにタスクバーの表示を消して、システムトレイにアイコンだけ表示したいので、初期状態を`frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);`にし、アイコン化された場合でも`frame.dispose();`するように設定
-- 実際に`VM`を終了する場合は、表示可能なウィンドウをすべて破棄してから`tray.remove(icon);`を実行してシステムトレイのアイコンを取り除く必要がある

上記のサンプルでは、フレームがアイコン化(最小化)されたときにタスクバーの表示を消して、システムトレイにアイコンだけ表示したいので、初期状態をframe.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);にしておき、アイコン化された場合でも、frame.dispose();するようにしています。
* 参考リンク [#reference]
- [[TrayIconのアニメーション>Swing/AnimatedTrayIcon]]
- [[TrayIconのダブルクリック>Swing/ClickTrayIcon]]

実際にVMを終了する場合は、表示可能なウィンドウをすべて破棄して(frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);)、システムトレイからもtray.remove(icon);してアイコンを取り除けばいいようです。
* コメント [#comment]
#comment
- `Ubuntu`だと通知スペースに表示されるのですが、背景色や位置がどうもうまくいっていないようです。 -- &user(aterai); &new{2007-05-08 (火) 20:23:38};
-- 位置は以下みたいにすれば適当に補正できそうですが、背景色はどうしたらいいんだろう? `g.setColor(UIManager.getColor("Panel.background"));g.fillRect(0,0,d.width,d.height);`とかするのは酷いか…。 -- &user(aterai); &new{2007-05-08 (火) 21:11:09};

**参考リンク [#n62f3502]
-[[TrayIconのアニメーション>Swing/AnimatedTrayIcon]]
-[[TrayIconのダブルクリック>Swing/ClickTrayIcon]]

**コメント [#na7a06ee]
- Ubuntu だと通知スペースに表示されるのですが、背景色や位置がどうもうまくいっていないようです。 -- [[terai]] &new{2007-05-08 (火) 20:23:38};
-- 位置は以下みたいにすれば適当に補正できそうですが、背景色はどうしたらいいんだろう? g.setColor(UIManager.getColor("Panel.background"));g.fillRect(0,0,d.width,d.height);とかするのは酷いか…。 -- [[terai]] &new{2007-05-08 (火) 21:11:09};
#code{{
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);
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);
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);とかしても変化無し。 -- [[terai]] &new{2007-05-09 (水) 13:54:25};
- メモ: [[TrayIcon does not support 8-bit alpha channel in Windows XP>http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6707273]] -- [[terai]] &new{2009-12-08 (火) 09:28:46};

-- `g.setBackground(new Color(0x0, true)); g.clearRect(0, 0, d.width, d.height);`などを設定しても変化無し。 -- &user(aterai); &new{2007-05-09 (水) 13:54:25};
- メモ: [https://bugs.openjdk.org/browse/JDK-6707273 TrayIcon does not support 8-bit alpha channel in Windows XP] -- &user(aterai); &new{2009-12-08 (火) 09:28:46};
- タスクバーのアイコンがなくなりシステムトレイのアイコンだけになりませんか? --  &new{2010-03-05 (金) 21:05:36};
-- Windowsでしか試していませんが、JFrameの代わりに、JDialogを使えばタスクバーには何も表示されないと思います(質問の意味を取り違えてなければいいのですが……)。 -- [[terai]] &new{2010-03-06 (土) 23:22:39};
-- `Windows`でしか試していませんが、`JFrame`の代わりに、`JDialog`を使えばタスクバーには何も表示されないと思います(質問の意味を取り違えてなければいいのですが……)。 -- &user(aterai); &new{2010-03-06 (土) 23:22:39};
- 消したいのはタイトルバーではなくてシステムトレイの隣のタスクバーアイコンです。文字で伝えるのは難しいですね。 --  &new{2010-03-08 (月) 17:28:43};
- スクリーンショットでJSTシステムトレイとタスクバーにあるやつです --  &new{2010-03-08 (月) 17:30:21};
-- http://terai.xrea.jp/swing/systemtray/screenshot1.png なら、JFrameの代わりに、JDialogを使えば表示されないはずです。 -- [[terai]] &new{2010-03-09 (火) 16:26:47};
- スクリーンショットで`JST`システムトレイとタスクバーにあるやつです --  &new{2010-03-08 (月) 17:30:21};
-- `JFrame`の代わりに、`JWindow`を使うのはどうでしょうか。 -- &user(aterai); &new{2010-03-09 (火) 16:26:47};
-- もしくは、[[JFrameのアイコンを非表示>Swing/DisableDefaultIcon]]のように透明なアイコンを設定する(クリックすると反応してしまいますが…)とか。 -- [[aterai]]
-- `4`年以上前で、いまさら過ぎるのですが、やっと理解しました。自分の回答は的外れすぎですね。アイコン化したときにタスクバーボタンを非表示にするには、`Window#dispose()`を実行するとよさそうです。このサンプルを修正して非表示にするよう変更しました。 -- &user(aterai); &new{2014-12-25 (火) 16:35:38};
-- [[TrayIconの使用中にJFrameを最小化したとき、タスクバーボタンを非表示にする>Swing/HideTaskbarButton]]に移動
- 間違えて、`Window#addWindowStateListener(...)`を使用していたので、`Window#addWindowListener(...)`を使用するように修正。 -- &user(aterai); &new{2014-12-25 (水) 17:57:58};

#comment