システムトレイが使える - TrayIcon
Java にできなかったこと
Java でデスクトップアプリケーションを作る場合、いろいろと制約があります。
たとえば、不定形ウィンドウとか、透明なウィンドウは今のところ使えません。いろいろと不便なこともあるのですが、プラットフォームによって実現できたり、できなかったりという機能は Java では取り入れにくいのは確かだと思います。
で、そんなできなかったことの 1 つにシステムトレイがあります。
Windows だとデフォルトで右下に表示される小さいアイコンがあるところですね。このシステムトレイですが、いつの間にかいろいろなプラットフォームで使えるようになってきています。
使える環境が増えてきたということは、Java に取り入れやすくなるということですね。
ということで、Java SE 6 からはシステムトレイが使えるようになったのでした。
アイコンを表示してみる
とりあえず、やってみましょう。
システムトレイを表すクラスは java.awt.SystemTray クラスです。そして、そこに表示するアイコンは java.awt.TrayIcon クラスを使用して表します。
まずは単にアイコンを表示させてみます。
| サンプルのソースコード | TrayIconSample1.java |
|---|
import java.awt.AWTException;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class TrayIconSample1 {
public TrayIconSample1() throws IOException, AWTException {
SystemTray tray = SystemTray.getSystemTray();
TrayIcon icon = new TrayIcon(ImageIO.read(new File("ukulele.png")));
tray.add(icon);
}
public static void main(String[] args) {
try {
new TrayIconSample1();
} catch (IOException ex) {
ex.printStackTrace();
} catch (AWTException ex) {
ex.printStackTrace();
}
}
}

SystemTray オブジェクトを取得するには SystemTray#getSystemTray メソッドを使用します。
そして、TrayIcon クラスのコンストラクタはいくつかありますが、ここでは最も単純な Image オブジェクトだけを引数に持つものを使用してみました。
Image オブジェクトは Image I/O を使用してもいいし、Toolkit#getImage を使用してもかまいません。
後は SystemTray#add メソッドで TrayIcon オブジェクトをシステムトレイに表示できます。
簡単ですね。
Windows で実行してみると、右図のようになりました。Fedora Core 4 でもやってみたのですが、例外が発生してしまいます。b56 で実行したので、もしかすると今後できるようになるかもしれません。
ツールチップとイベント
さて、次はツールチップとイベントを扱っていきましょう。
| サンプルのソースコード | TrayIconSample2.java |
|---|
SystemTray tray = SystemTray.getSystemTray();
Image image = ImageIO.read(new File("ukulele.png"));
TrayIcon icon = new TrayIcon(image, "サンプル");
icon.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.println("ACTION!!");
System.exit(0);
}
});
tray.add(icon);

ツールチップを表示させるには、コンストラクタで指定する方法と、setToolTip メソッドを使用する方法があります。ここでは、コンストラクタで指定してみました。
実行してマウスカーソルをアイコンのそばに置いておくと、ツールチップが表示されます。
イベントも普通のコンポーネントとまったく同じです。TrayIcon クラスでは ActionEvent が発生するのが、アイコンをクリックされたときのようです。
上のコードではマウスでクリックされたら、アプリケーションを終了させています。
ActionEvent 以外には MouseEvent と MouseMotionEvent が扱えるようです。
ポップアップメニューを表示させる
次はポップアップメニューです。
ポップアップメニューもあっけないほど簡単。
| サンプルのソースコード | TrayIconSample3.java |
|---|
SystemTray tray = SystemTray.getSystemTray();
Image image = ImageIO.read(new File("ukulele.png"));
PopupMenu menu = new PopupMenu("サンプル");
menu.add(new MenuItem("これ"));
menu.add(new MenuItem("それ"));
TrayIcon icon = new TrayIcon(image, "サンプル", menu);
icon.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.println("ACTION!!");
System.exit(0);
}
});
tray.add(icon);

PopupMenu オブジェクトを生成して、普通通りに MenuItem オブジェクトを追加して、必要があれば MenuItem オブジェクトにイベント処理をくっつけて。
そして、TrayIcon クラスのコンストラクタで指定するだけです。setPopupMenu メソッドで設定することもできます。
ポップアップメニューはマウスの右クリックで表示されます。
メッセージを表示させてみよう
最後はダイアログのように表示されるメッセージです。よくありますよね。ネットワークがつながったとか、更新の準備が整いましたとか。あれです、あれ。
| サンプルのソースコード | TrayIconSample4.java |
|---|
メッセージを表示させるには TrayIcon#displayMessage メソッドを使用します。
それではアイコンを左クリックしたときにメッセージを表示させるようにしてみましょう。
icon = new TrayIcon(image, "サンプル", menu);
icon.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent event) {
if (event.getButton() == MouseEvent.BUTTON1) {
icon.displayMessage("メッセージ", "警告", TrayIcon.MessageType.WARNING);
}
}
});

displayMessage メソッドは JOptionPane クラスのような使い方をします。
第 1 引数がダイアログのタイトル、第 2 がメッセージ、最後がいっしょに表示するアイコンの種類を指定します。
Windows で実行すると、右のようになりました。
これで、一歩ネイティブのデスクトップアプリケーションに近づくことができました。
おまけ
今まで Java のデスクトップアプリケーションは、システムトレイが使えなかったので、どうしてもタスクバーに表示しなければなりませんでした。
でも、SystemTray クラス/TrayIcon クラスを使えばもうそんなことは過去のこと。
せっかくなので、システムトレイだけで動作するアプリケーションを作ってみました。
| サンプルのソースコード | Alarm.java |
|---|


実行させたら、システムトレイのアイコンを右クリックして時刻設定をします。
時刻設定には JSpinner クラスを使用しているのでが、このクラスで時間を編集するのはつらいですね。でも、今回はサンプルなのでご了承ください。
設定した時刻になるとメッセージが表示され、アイコンも変更します。
このコードはたったの 100 行足らず。簡単ですね。
おしむらくはメッセージがいつ消えるか分からないので、メッセージが消えるのとアイコンを元に戻すことを同期させられないことがあります。
このメッセージはプラットフォームに依存しているようなので、いつ消えるかは OS やウィンドウシステムによってしまうのです。ちょっと、残念なのですが、しかたないですね。
(Nov. 2005)
