SystemTray – 常駐程式

systemtray.gif

(圖片來源:http://java.sun.com/docs/books/tutorial/uiswing/misc/systemtray.html)

我們常看到的在工作列右邊的常駐程式,可以用java.awt.SystemTray來寫,搭配java.awt.TrayIcon來顯示圖示。這個功能必須使用Java SE 6或更新版本,這兩個class都在java.awt這個package之下。

由於SystemTray實作成單體(即一個Java程式只能有唯一一個SystemTray的實體或稱物件),所以要取得SystemTray的實體必須呼叫它的static getSystemTray method如下:

SystemTray.getSystemTray();

但在使用之前,可以先檢查該作業系統是否有支援:

SystemTray.isSupported();

支援傳回true,不支援則傳回false

一個SystemTray可以包含一個或多個TrayIcon,使用add() method來增加至SystemTray中:

tray.add(trayIcon);

註:tray表示SystemTray的實體,trayIcon表示TrayIcon的實體。

TrayIcon可以顯示一個tooltip,如上圖的"Sun TrayIcon"黃色小框框:

trayIcon.displayMessage(String caption, String text, TrayIcon.MessageType messageType)

messageType 共有4個參數,如下:

  • TrayIcon.MessageType.ERROR – 錯誤訊息error.png
  • TrayIcon.MessageType.INFO – 資訊訊息info.png
  • TrayIcon.MessageType.NONE – 簡單訊息(無圖示)
  • TrayIcon.MessageType.WARNING – 警告訊息warning.png

註:trayIcon表示TrayIcon的實體。

TrayIcon可監聽的滑鼠事件:

MouseEvents (pressed, released, and clicked)

  • pressed:按住不放
  • released:放開
  • clicked:按一下

程式碼如下:

/* SysTray.java
* Created on 2008/10/11
* Author Tony
*
*/

import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JOptionPane;

public class SysTray {
//icon object
private TrayIcon trayIcon;
//SystemTray object
private SystemTray tray = null;
//取得圖示,如果找不到圖,在系統列上會是空白的
private final Image image = Toolkit.getDefaultToolkit().getImage(“image/tray.gif");

//跳出式選單
private PopupMenu popup = new PopupMenu();
private MenuItem openItem = null;
private MenuItem optionItem = null;
private MenuItem aboutItem = null;
private MenuItem exitItem = null;

public SysTray(){
//檢查OS是否支援SystemTray
if(SystemTray.isSupported()){

//每個Java程式只能有一個SystemTray實體
tray = SystemTray.getSystemTray();

//設定選單
setMenu();

//設定trayIcon(圖片,滑鼠指上去的Tip訊息,選單)
trayIcon = new TrayIcon(image, “我的系統常駐程式", popup);

//設定圖示自動變更尺寸
trayIcon.setImageAutoSize(true);

try {
//把trayIcon加入tray中
tray.add(trayIcon);
} catch (AWTException e) {
System.err.println(“TrayIcon could not be added.");
}

//設定事件
setEvent();
}else{
JOptionPane.showMessageDialog(null, “SystemTray not support!");
}
}

private void setMenu(){
//加入選單
openItem = new MenuItem(“開啟系統主界面");
optionItem = new MenuItem(“選項");
aboutItem = new MenuItem(“關於本程式");
exitItem = new MenuItem(“離開");

popup.add(openItem);
popup.add(optionItem);
popup.add(aboutItem);
//加入分隔線
popup.addSeparator();
popup.add(exitItem);
}

private void setEvent(){
//設定滑鼠事件監聽器
MouseListener mouseListener = new MouseListener() {
//Click
public void mouseClicked(MouseEvent e) {
//按左鍵才顯示Tip訊息
if (e.getButton() == MouseEvent.BUTTON1){
trayIcon.displayMessage(“^____^ :",
“使用displayMessage()可以用來通知使用者訊息喔~~~ \n滑鼠右鍵則可以顯示選單。",
TrayIcon.MessageType.INFO);
}
System.out.println(“Tray Icon – 按一下!");
}
//Enter
public void mouseEntered(MouseEvent e) {
System.out.println(“Tray Icon – 滑鼠進入!無效");
}
//Exit
public void mouseExited(MouseEvent e) {
System.out.println(“Tray Icon – 滑鼠離開!無效");
}

public void mousePressed(MouseEvent e) {
System.out.println(“Tray Icon – 滑鼠按下!");
}

public void mouseReleased(MouseEvent e) {
System.out.println(“Tray Icon – 滑鼠放開!");
}
};

//openItem按鈕事件
ActionListener openListener = new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null, “開啟系統主界面");
}
};

//optionItem按鈕事件
ActionListener optionListener = new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null, “開啟選項");
}
};

//aboutItem按鈕事件
ActionListener aboutListener = new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null, “SystemTray 系統匣\n\nTonyBox\n\nhttps://tonybox.wordpress.com");
}
};

//aboutItem按鈕事件
ActionListener exitListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, “離開");
System.out.println(“離開");
System.exit(0);
}
};

//加入事件
openItem.addActionListener(openListener);
optionItem.addActionListener(optionListener);
aboutItem.addActionListener(aboutListener);
exitItem.addActionListener(exitListener);
trayIcon.addMouseListener(mouseListener);
}

public static void main(String[] args) {
//Test
new SysTray();
}

}

7 回應 to “SystemTray – 常駐程式”


  1. 1 vita 星期日 14 十二月, 2008 於 9:44 下午

    我是java新手,因為工作需求,要用system tray,可是我不知道要如何包這些程式,才能讓client執行及常駐在電腦裏

    請指點一下方向, 謝謝!!

  2. 2 Tony 星期一 15 十二月, 2008 於 2:26 下午

    你好:
    Java我也還在學習中.
    有幾個方法可以打包Java檔

    1.使用Eclipse開發
    在專案上按右鍵->Export->Java->Runnable JAR file
    Eclipse會自動幫你產生可執行的jar檔

    2.command line
    首先,在你的class檔的目錄下加一個mainfest檔(沒附檔名)
    檔內文字如下:

    Main-Class: SysTray

    !注意事項:
    1.在冒號後要空一格
    2.SysTray為你的main class的檔名(注意沒有.class)
    3.如果有Package要寫成myPackage.SysTray
    4.最後必須按Enter讓遊標換到下一行
    很鎖碎的重點,缺一就無法執行

    然後在命令提示字元下輸入以下指令:
    jar cvfm SysTray.jar manifest *.class

    SysTray.jar就是你要產生的jar檔

    如此就完成啦~~
    接下來可以輸入
    java -jar SysTray.jar 來執行
    或在檔案總管雙按該檔也可以執行

    雖然它是可執行檔,可是你要部署的電腦也必須有JVM才能執行喔
    參考資料:
    http://java.sun.com/docs/books/tutorial/deployment/jar/basicsindex.html

  3. 3 JAVA新手 星期二 5 七月, 2011 於 4:59 下午

    請問程式縮到右下角後,要怎麼再把它叫起來?
    你開啟系統主界面那邊的程式碼沒有提到…

  4. 6 JAVA菜鳥... 星期二 14 二月, 2012 於 8:29 下午

    不太懂…
    縮小後,在
    //openItem按鈕事件
    ActionListener openListener = new ActionListener(){
    public void actionPerformed(ActionEvent arg0) {
    JOptionPane.showMessageDialog(null, “開啟系統主界面”);
    }
    };

    裡面再new 一個
    XXX app = new XXX();
    app.setSize(300, 300);
    app.setVisible(true);

    這樣不是又再叫一個一樣的程式出來? 0.0a

    • 7 Tony 星期三 15 二月, 2012 於 5:50 下午

      沒錯,所以
      XXX app = new XXX();
      app.SetSize(300,300);
      —————————–
      以上這部份通常會寫在建構式中,所以只會建一次,
      並且通常會讓它隱藏(如果需求是一開始不可見的話)
      app.setVisible(false);

      =========================
      接著只要在需要出現的地方
      app.setVisible(true);
      隱藏就
      app.setVisible(false);

      這樣只建一次,之後只是單純控制它的可見性而以~~


Comments are currently closed.