JavaFX+Jfoenix 学习笔记(十)--系统托盘及解决中文乱码问题

前言

桌面应用少不了要用到系统托盘,但是JavaFX并没有给我们提供系统托盘(至少我没找见),不过也不要紧,我们可以用java.awt.SystemTray。

1、创建系统托盘,并添加显示、隐藏、退出按钮

// 我们的自定义系统托盘
	class MySysTray {
		private TrayIcon trayIcon = null;
		private Timeline timeline = new Timeline();
	 
		public void initSystemTray() {
			// 1、创建托盘按钮
			PopupMenu popupMenu = new PopupMenu();		
			MenuItem showItem = new MenuItem("显示"); popupMenu.add(showItem);
			MenuItem hideItem = new MenuItem("隐藏"); popupMenu.add(hideItem);
			MenuItem quitItem = new MenuItem("退出"); popupMenu.add(quitItem);
			
			// 2、创建动作事件监听器(awt的古老操作)
			ActionListener actionListener = new ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					// 多次使用显示和隐藏设置false
					Platform.setImplicitExit(false);
					
					// 获得按钮并执行相应操作
					MenuItem item = (MenuItem) e.getSource();
					if (item.getLabel().equals("退出")) {
						// 移除托盘图标
						SystemTray.getSystemTray().remove(trayIcon);
						// 关闭应用
						Platform.exit();
						// 延迟500毫秒关闭进程
						Timeline timeline = new Timeline();
						timeline.setCycleCount(1);
						timeline.setAutoReverse(false);
				    	KeyFrame keyFrame = new KeyFrame(Duration.millis(500), new EventHandler() {
				            public void handle(ActionEvent t) {	
				            	// 彻底退出进程
				            	System.exit(0);
				            }
				        });
				    	timeline.getKeyFrames().clear();
				    	timeline.getKeyFrames().add(keyFrame);
				    	timeline.play();
					}
					
					else if (item.getLabel().equals("显示")) {
						Platform.runLater(new Runnable() {
							public void run() {
								stage.show();
							}
						});
					}
					
					else if (item.getLabel().equals("隐藏")) {
						Platform.runLater(new Runnable() {
							public void run() {
								stage.hide();
							}
						});
					}
				}
			};
			// 3、给按钮添加动作事件监听
			showItem.addActionListener(actionListener);
			quitItem.addActionListener(actionListener);
			hideItem.addActionListener(actionListener);
	 
			try {
				// 4、我们的托盘图标
				trayIcon = new TrayIcon(ImageIO.read(new File(Constants.RESOURCES + "img" + File.separator + "sysicon.png")), Constants.TITLE, popupMenu);
				// 5、鼠标悬浮时的提示信息
				trayIcon.setToolTip(Constants.TITLE);
				// 6、添加到系统托盘
				SystemTray.getSystemTray().add(trayIcon);
				// 7、给托盘图标添加鼠标监听
				trayIcon.addMouseListener(new MouseListener() {
					public void mouseClicked(MouseEvent e) {
						// 多次使用显示和隐藏设置false
						Platform.setImplicitExit(false);
						// 鼠标单击一次
						if (e.getClickCount() == 2) {
							timeline.stop();
							timeline.setCycleCount(1);
							timeline.setAutoReverse(false);
					    	KeyFrame keyFrame = new KeyFrame(Duration.millis(10), new EventHandler() {
					            public void handle(ActionEvent t) {	                        
					            	if (stage.isShowing()) {
					            		stage.hide();
									}else{
										stage.show();
									}	
					            }
					        });
					    	timeline.getKeyFrames().clear();
					    	timeline.getKeyFrames().add(keyFrame);
					    	timeline.play();				
						}
					}
					
					public void mouseReleased(MouseEvent e) {}
					public void mousePressed(MouseEvent e) {}
					public void mouseExited(MouseEvent e) {}
					public void mouseEntered(MouseEvent e) {}
				});
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

说明及注意事项

1、使用Timeline来控制双击事件时最大化和隐藏的时间延迟;

2、使用Platform.runLater(new Runnable() {})来执行单击最大化、最小化和退出操作;

3、使用java.awt.MenuItem创建菜单项(按钮);

4、通过设置Platform.setImplicitExit(false),使应用可以多次切换显示和隐藏;

5、一般使用Platform.exit();关闭应用并不能从人物关闭其中关闭进程,随意最好再使用System.exit(0)退出进程;

6、如果不在stage.show()前添加Platform.setImplicitExit(false),那么点击窗口的关闭按钮后就不能再通过系统托盘显示;

2、系统托盘中文乱码处理

如果系统托盘中文乱码(原因是JVM中的编码格式跟windows默认编码不一致),肯定是你的JVM的环境变量没有设置这个-Dfile.encoding=GB18030,这个时候如果你用的Eclipse在Run Configurations中的VM arguments中添加即可,如下图:

JavaFX+Jfoenix 学习笔记(十)--系统托盘及解决中文乱码问题_第1张图片

如果你实在cmd中启动,同样设置下设个属性即可,如下图:

如果你是打包成EXE程序了,那么你可能不会遇到乱码问题。

3、实例

package zkh.javafx.learn.systemtray;

import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;

import javax.imageio.ImageIO;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import javafx.util.Duration;
import zkh.javafx.util.Constants;

/**
 * SystemTray
 */
// 继承javafx.application.Application是JavaFX的开始
public class SysTray extends Application {
	
	public Stage stage = null;
	
	/**
	 * Stage:就是你能看到的整个软件界面(窗口)
	 * Scene:就是除了窗口最上面有最大、最小化及关闭按钮那一行及窗口边框外其它的区域(场景)
	 * 场景(Scene)是一个窗口(Stage)必不可少的
	 */
	@Override
	public void start(Stage stage) throws Exception {
		// (如果需要的话)定位横纵坐标,避免太靠边上遮盖菜单栏,,这两行如果不屑,一般电脑默认是居中屏幕显示,但在有些电脑会跑偏
        // stage.setX(0);stage.setY(4);
        // stage和Scene不再注释
		this.stage = stage;
		// 创建一个标签,用于存放我们的Hello World文本,并设置让它在父容器中居中
		Label label = new Label("系统托盘演示"); label.setAlignment(Pos.CENTER);
		
		// 添加到系统托盘
		new MySysTray().initSystemTray();
		// (如果不在stage.show()前使用这个,那么点击窗口的关闭按钮后就不能再通过系统托盘显示)多次使用显示和隐藏设置false
        Platform.setImplicitExit(false);
        
		// 1、初始化一个场景
		Scene scene = new Scene(label, 800, 600);
		// 2、将场景放入窗口
		stage.setScene(scene);
		// 3、打开窗口
		stage.show();
	}

	
	// 我们的自定义系统托盘
	class MySysTray {
		private TrayIcon trayIcon = null;
		private Timeline timeline = new Timeline();
	 
		public void initSystemTray() {
			// 1、创建托盘按钮
			PopupMenu popupMenu = new PopupMenu();		
			MenuItem showItem = new MenuItem("显示"); popupMenu.add(showItem);
			MenuItem hideItem = new MenuItem("隐藏"); popupMenu.add(hideItem);
			MenuItem quitItem = new MenuItem("退出"); popupMenu.add(quitItem);
			
			// 2、创建动作事件监听器(awt的古老操作)
			ActionListener actionListener = new ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					// 多次使用显示和隐藏设置false
					Platform.setImplicitExit(false);
					
					// 获得按钮并执行相应操作
					MenuItem item = (MenuItem) e.getSource();
					if (item.getLabel().equals("退出")) {
						// 移除托盘图标
						SystemTray.getSystemTray().remove(trayIcon);
						// 关闭应用
						Platform.exit();
						// 延迟500毫秒关闭进程
						Timeline timeline = new Timeline();
						timeline.setCycleCount(1);
						timeline.setAutoReverse(false);
				    	KeyFrame keyFrame = new KeyFrame(Duration.millis(500), new EventHandler() {
				            public void handle(ActionEvent t) {	
				            	// 彻底退出进程
				            	System.exit(0);
				            }
				        });
				    	timeline.getKeyFrames().clear();
				    	timeline.getKeyFrames().add(keyFrame);
				    	timeline.play();
					}
					
					else if (item.getLabel().equals("显示")) {
						Platform.runLater(new Runnable() {
							public void run() {
								stage.show();
							}
						});
					}
					
					else if (item.getLabel().equals("隐藏")) {
						Platform.runLater(new Runnable() {
							public void run() {
								stage.hide();
							}
						});
					}
				}
			};
			// 3、给按钮添加动作事件监听
			showItem.addActionListener(actionListener);
			quitItem.addActionListener(actionListener);
			hideItem.addActionListener(actionListener);
	 
			try {
				// 4、我们的托盘图标
				trayIcon = new TrayIcon(ImageIO.read(new File(Constants.RESOURCES + "img" + File.separator + "sysicon.png")), Constants.TITLE, popupMenu);
				// 5、鼠标悬浮时的提示信息
				trayIcon.setToolTip(Constants.TITLE);
				// 6、添加到系统托盘
				SystemTray.getSystemTray().add(trayIcon);
				// 7、给托盘图标添加鼠标监听
				trayIcon.addMouseListener(new MouseListener() {
					public void mouseClicked(MouseEvent e) {
						// 多次使用显示和隐藏设置false
						Platform.setImplicitExit(false);
						// 鼠标单击一次
						if (e.getClickCount() == 2) {
							timeline.stop();
							timeline.setCycleCount(1);
							timeline.setAutoReverse(false);
					    	KeyFrame keyFrame = new KeyFrame(Duration.millis(10), new EventHandler() {
					            public void handle(ActionEvent t) {	                        
					            	if (stage.isShowing()) {
					            		stage.hide();
									}else{
										stage.show();
									}	
					            }
					        });
					    	timeline.getKeyFrames().clear();
					    	timeline.getKeyFrames().add(keyFrame);
					    	timeline.play();				
						}
					}
					
					public void mouseReleased(MouseEvent e) {}
					public void mousePressed(MouseEvent e) {}
					public void mouseExited(MouseEvent e) {}
					public void mouseEntered(MouseEvent e) {}
				});
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	
	public static void main( String[] args ){
		// 启动软件
		Application.launch(args);
    }

}

效果动图:

JavaFX+Jfoenix 学习笔记(十)--系统托盘及解决中文乱码问题_第2张图片

4、源代码(不推荐,文章基本都有了)

JavaFX+Jfoenix 学习笔记(十)--系统托盘及解决中文乱码问题源码

好了,多看注释!

你可能感兴趣的:(javafx,jfoenix,系统托盘,中文乱码,SystemTray,JavaFX+Jfoenix,学习笔记)