<dependency>
<groupId>de.roskenetgroupId>
<artifactId>springboot-javafx-supportartifactId>
<version>2.1.6version>
dependency>
让App类继承AbstractJavaFxApplicationSupport,注意main方法。
public class App extends AbstractJavaFxApplicationSupport{
public static void main(String[] args) {
launch(args);
}
@Bean
public Gson gson() {
return new Gson();
}
@Override
public void start(Stage stage) throws IOException {
stage.setTitle(R.title);
BorderPane root = new BorderPane();
VBox vBox = new VBox();
HBox hBox = new HBox();
Label label = new Label();
label.setText(R.sysTitle+"已经启动");
label.setTextFill(Paint.valueOf("Green"));
Label labelUrl = new Label();
String port = getBaseCfgFromProperties();
String labelUrlStr = "127.0.0.1:"+port;
labelUrl.setOnMouseClicked(event -> {
CommonUtil.openUrl(labelUrlStr);
});
labelUrl.setText(labelUrlStr);
labelUrl.setTextFill(Paint.valueOf("Red"));
labelUrl.setStyle("-fx-background-color: #7ee;");
hBox.getChildren().addAll(label,labelUrl);
hBox.setAlignment(Pos.BASELINE_CENTER);
hBox.setPrefHeight(25);
hBox.setSpacing(5);
//---------------------------
HBox hBox1 = new HBox();
Label label1 = new Label();
label1.setText(R.readme);
label1.setTextFill(Paint.valueOf("Gray"));
hBox1.getChildren().add(label1);
hBox1.setAlignment(Pos.BASELINE_CENTER);
hBox1.setPrefHeight(25);
//---------------------------
vBox.getChildren().addAll(hBox,hBox1);
root.setCenter(vBox);
stage.setScene(new Scene(root,300,50));
Image icon = new Image(R.ICON, 32, 32, false, false);
stage.getIcons().add(icon);
MySystemTray.getInstance(stage);
stage.show();
}
public static String getBaseCfgFromProperties() throws IOException {
InputStream props = App.class.getClassLoader().getResourceAsStream("application.properties");
Properties properties = new Properties();
properties.load(props);
return (String) properties.get("server.port");
}
}
package top.lcpsky.message.util;
import javafx.application.Platform;
import javafx.stage.Stage;
import lombok.Synchronized;
import top.lcpsky.message.App;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.io.InputStream;
/**
* 自定义系统托盘(单例模式)
*
* @author
* @date
*/
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("Desktop");
//菜单项(退出)
exitItem = new MenuItem("Logout");
//此处不能选择ico格式的图片,要使用16*16的png格式的图片
InputStream img = MySystemTray.class.getClassLoader().getResourceAsStream("images/icon.png");
Image image = null;
try {
image = ImageIO.read(img);
} catch (IOException e) {
e.printStackTrace();
}
//系统托盘图标
trayIcon = new TrayIcon(image);
//初始化监听事件(空)
showListener = e -> Platform.runLater(() -> {
});
exitListener = e -> {
};
mouseListener = new MouseAdapter() {
};
}
public static MySystemTray getInstance(Stage stage) {
if (instance == null) {
synchronized (MySystemTray.class){
if (instance == null) {
instance = new MySystemTray(stage);
}
}
}
return instance;
}
private MySystemTray(Stage stage) {
try {
//检查系统是否支持托盘
if (!SystemTray.isSupported()) {
//系统托盘不支持
return;
}
//设置图标尺寸自动适应
trayIcon.setImageAutoSize(true);
//系统托盘
SystemTray tray = SystemTray.getSystemTray();
//弹出式菜单组件
final PopupMenu popup = new PopupMenu();
popup.add(showItem);
popup.add(exitItem);
trayIcon.setPopupMenu(popup);
//鼠标移到系统托盘,会显示提示文本
trayIcon.setToolTip(R.title);
listen(stage);
tray.add(trayIcon);
} catch (Exception e) {
//系统托盘添加失败
System.out.println(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 -> {
Notification.displayTray("短信服务端","短信服务控制程序退出");
Platform.runLater(()->{
System.exit(0);
});
};
//鼠标行为事件: 单机显示stage
mouseListener = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
//鼠标左键
if (e.getButton() == MouseEvent.BUTTON1) {
Notification.displayTray("短信服务端","短信服务控制程序已显示");
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();
try {
CommonUtil.openUrl("127.0.0.1:"+App.getBaseCfgFromProperties());
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
这样做可以直接让用户看到程序界面,很利好那些对软件不太数据的用户。
public class CommonUtil {
public static void openUrl(String url){
try {
String stmt = "start explorer http://"+url;
String[] command = {"cmd", "/c", stmt};
Runtime runtime = Runtime.getRuntime();
runtime.exec(command);
} catch (IOException e) {
e.printStackTrace();
}
}
}
通过托盘退出程序效果。只找到awt与系统交互的工具类,如下图所示。
package top.lcpsky.message.util;
import javax.imageio.ImageIO;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
/**
* @author: Administrator
* @date: 2021/09/17 15:29
* @description:
*/
public class Notification {
public static void displayTray(String title,String desc) {
InputStream img = Notification.class.getClassLoader().getResourceAsStream("images/icon.png");
Image image = null;
try {
image = ImageIO.read(img);
} catch (IOException e) {
e.printStackTrace();
}
//Obtain only one instance of the SystemTray object
SystemTray tray = SystemTray.getSystemTray();
//If the icon is a file
//Alternative (if the icon is on the classpath):
TrayIcon trayIcon = new TrayIcon(image, title);
//Let the system resize the image if needed
trayIcon.setImageAutoSize(true);
//Set tooltip text for the tray icon
trayIcon.setToolTip(desc);
try {
tray.add(trayIcon);
} catch (AWTException e) {
e.printStackTrace();
}
trayIcon.displayMessage(title, desc, TrayIcon.MessageType.INFO);
}
}