@Override public void start(Stage stage) throws Exception { log.info("start"); super.start(stage); //右下角圖標 MySystemTray.getInstance(stage); }
package com.ceadeal.javafxboot.ctrl; 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.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.net.URL; import javafx.application.Platform; import javafx.stage.Stage; import lombok.extern.slf4j.Slf4j; /** * 自定義系統托盤(單例模式) * */ @Slf4j public class MySystemTray { private static MySystemTray instance; private static MenuItem showItem; private static MenuItem exitItem; private static TrayIcon trayIcon; private static ActionListener showListener; private static ActionListener exitListener; private static MouseListener mouseListener; //右小角,最小化. //菜單項(打開)中文亂碼的問題是編譯器的鍋,如果使用IDEA,需要在Run-Edit Configuration在LoginApplication中的VM Options中添加-Dfile.encoding=GBK //如果使用Eclipse,需要右鍵Run as-選擇Run Configuration,在第二欄Arguments選項中的VM Options中添加-Dfile.encoding=GBK //打包成exe安裝后打開不會亂碼 static{ //執行stage.close()方法,窗口不直接退出 Platform.setImplicitExit(false); //菜單項(打開)中文亂碼的問題是編譯器的鍋,如果使用IDEA,需要在Run-Edit Configuration在LoginApplication中的VM Options中添加-Dfile.encoding=GBK //如果使用Eclipse,需要右鍵Run as-選擇Run Configuration,在第二欄Arguments選項中的VM Options中添加-Dfile.encoding=GBK showItem = new MenuItem("打開"); //菜單項(退出) exitItem = new MenuItem("退出"); //此處不能選擇ico格式的圖片,要使用16*16的png格式的圖片 URL url = MySystemTray.class.getResource("/icon/1.png"); Image image = Toolkit.getDefaultToolkit().getImage(url); //系統托盤圖標 trayIcon = new TrayIcon(image); //初始化監聽事件(空) showListener = e -> Platform.runLater(() -> {}); exitListener = e -> {}; mouseListener = new MouseAdapter() {}; } public static MySystemTray getInstance(Stage stage){ if(instance == null){ instance = new MySystemTray(stage); } return instance; } private MySystemTray(Stage stage){ try { //檢查系統是否支持托盤 if (!SystemTray.isSupported()) { //系統托盤不支持 log.info(Thread.currentThread().getStackTrace()[ 1 ].getClassName() + ":系統托盤不支持"); return; } //設置圖標尺寸自動適應 trayIcon.setImageAutoSize(true); //系統托盤 SystemTray tray = SystemTray.getSystemTray(); //彈出式菜單組件 final PopupMenu popup = new PopupMenu(); popup.add(showItem); popup.add(exitItem); trayIcon.setPopupMenu(popup); //鼠標移到系統托盤,會顯示提示文本 trayIcon.setToolTip("CMS"); listen(stage); tray.add(trayIcon); } catch (Exception e) { //系統托盤添加失敗 log.error(Thread.currentThread().getStackTrace()[ 1 ].getClassName() + ":系統添加失敗", e); } } /** * 更改系統托盤所監聽的Stage */ public void listen(Stage stage){ //防止報空指針異常 if(showListener == null || exitListener == null || mouseListener == null || showItem == null || exitItem == null || trayIcon == null){ return; } //移除原來的事件 showItem.removeActionListener(showListener); exitItem.removeActionListener(exitListener); trayIcon.removeMouseListener(mouseListener); //行為事件: 點擊"打開"按鈕,顯示窗口 showListener = e -> Platform.runLater(() -> showStage(stage)); //行為事件: 點擊"退出"按鈕, 就退出系統 exitListener = e -> { System.exit(0); }; //鼠標行為事件: 單機顯示stage mouseListener = new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { //鼠標左鍵 if (e.getButton() == MouseEvent.BUTTON1) { showStage(stage); } } }; //給菜單項添加事件 showItem.addActionListener(showListener); exitItem.addActionListener(exitListener); //給系統托盤添加鼠標響應事件 trayIcon.addMouseListener(mouseListener); } /** * 關閉窗口 */ public void hide(Stage stage){ Platform.runLater(() -> { //如果支持系統托盤,就隱藏到托盤,不支持就直接退出 if (SystemTray.isSupported()) { //stage.hide()與stage.close()等價 stage.hide(); } else { System.exit(0); } }); } /** * 點擊系統托盤,顯示界面(並且顯示在最前面,將最小化的狀態設為false) */ private void showStage(Stage stage){ //點擊系統托盤, Platform.runLater(() -> { if(stage.isIconified()){ stage.setIconified(false);} if(!stage.isShowing()){ stage.show(); } stage.toFront(); }); } }
