javafx NullPointerException与controlsfx通知组件

javafx NullPointerException与controlsfx通知组件,java,javafx,javafx-2,system-tray,controlsfx,Java,Javafx,Javafx 2,System Tray,Controlsfx,我想开发一个应用程序,它使用controlsfx通知在系统托盘模式下显示一些通知。在正常模式下,我的应用程序运行良好,可以成功显示通知。但当我在系统托盘中隐藏后台时,会发生NullPointerException。我不知道怎样才能解决这个问题 import java.awt.AWTException; 导入java.awt.MenuItem; 导入java.awt.PopupMenu; 导入java.awt.SystemTray; 导入java.awt.Toolkit; 导入java.awt.T

我想开发一个应用程序,它使用controlsfx通知在系统托盘模式下显示一些通知。在正常模式下,我的应用程序运行良好,可以成功显示通知。但当我在系统托盘中隐藏后台时,会发生NullPointerException。我不知道怎样才能解决这个问题

import java.awt.AWTException;
导入java.awt.MenuItem;
导入java.awt.PopupMenu;
导入java.awt.SystemTray;
导入java.awt.Toolkit;
导入java.awt.TrayIcon;
导入java.awt.event.ActionListener;
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.event.EventHandler;
导入javafx.fxml.fxmloader;
导入javafx.scene.Parent;
导入javafx.scene.scene;
导入javafx.stage.stage;
导入javafx.stage.WindowEvent;
公共类tryi内涵化扩展应用{
第一次私人布尔运算;
私人运输公司;
@凌驾
public void start(Stage)引发异常{
第一次=正确;
父根=fxmloader.load(getClass().getResource(“FXMLDocument.fxml”);
场景=新场景(根);
createTrayIcon(阶段);
第一次=正确;
Platform.setImplicitExit(false);
舞台场景;
stage.show();
}
公共空间createTrayIcon(最后阶段){
if(SystemTray.issuported()){
//获取SystemTray实例
SystemTray=SystemTray.getSystemTray();
//加载图像
java.awt.Image Image=null;
image=Toolkit.getDefaultToolkit().getImage(“icons\\iconify.png”);
stage.setOnCloseRequest(新的EventHandler(){
@凌驾
公共无效句柄(WindowEvent t){
隐藏(阶段);
}
});
//创建一个操作侦听器,以侦听在托盘图标上执行的默认操作
最终ActionListener closeListener=新ActionListener(){
@凌驾
public void actionPerformed(java.awt.event.ActionEvent e){
stage.hide();
}
};
ActionListener showListener=新建ActionListener(){
@凌驾
public void actionPerformed(java.awt.event.ActionEvent e){
Platform.runLater(新的Runnable(){
@凌驾
公开募捐{
stage.show();
}
});
}
};
//创建一个弹出菜单
PopupMenu popup=新建PopupMenu();
MenuItem showItem=新MenuItem(“开放应用程序”);
showItem.addActionListener(showListener);
添加(showItem);
MenuItem closeItem=新MenuItem(“退出”);
closeItem.addActionListener(closeListener);
弹出。添加(关闭项);
///…添加其他项目
//建造一个火车站
trayIcon=新trayIcon(图像,“Systray”,弹出窗口);
//设置TrayIcon属性
trayIcon.addActionListener(showListener);
// ...
//添加托盘图像
试一试{
托盘。添加(trayIcon);
}捕获(awtexe){
系统错误println(e);
}
// ...
}
}
公共void showProgramIsMinimizedMsg(){
//仅在第一次显示消息时
如果(第一次){
trayIcon.displayMessage(“系统托盘”,
“图像化”,
TrayIcon.MessageType.INFO);
第一次=错误;
}
}
私人空间隐藏(最后阶段){
Platform.runLater(新的Runnable(){
@凌驾
公开募捐{
if(SystemTray.issuported()){
stage.hide();
showProgramIsMinimizedMsg();
}否则{
系统出口(0);
系统输出打印项次(“不支持系统托盘”);
}
}
});
}
/**
*@param指定命令行参数
*/
公共静态void main(字符串[]args){
发射(args);
}
}
这是我的控制器类:

import java.net.URL;
导入java.util.ResourceBundle;
导入java.util.Timer;
导入java.util.TimerTask;
导入javafx.application.Platform;
导入javafx.event.ActionEvent;
导入javafx.fxml.fxml;
导入javafx.fxml.Initializable;
导入javafx.scene.control.Label;
导入javafx.stage.stage;
导入org.controlsfx.control.Notifications;
公共类FXMLDocumentController实现可初始化{
@FXML
自有品牌;
@FXML
私有无效把手按钮操作(ActionEvent事件){
Stage Stage=(Stage)label.getScene().getWindow();
stage.hide();
}
public void createNotification(){
通知。创建()
.text(“本通知”)
.标题(“通知”)
.showInformation();
}
@凌驾
公共void初始化(URL、ResourceBundle rb){
定时器=新定时器();
timer.scheduleAtFixedRate(新TimerTask(){
@凌驾
公开募捐{
Platform.runLater(()->createNotification());
}
}, 5000, 10000);
}
}

我意识到,当阶段进入隐藏模式,并且当通知需要在阶段中显示时,通知组件无法找到阶段时,会发生此异常。在网上搜索后,我找到了两种解决这个问题的方法

解决方案1:

打开舞台并显示通知。 通过这种方式,我们应该检查阶段是否隐藏,打开它,并显示通知。 为此,我们必须在CreateNotification Meth中添加此条件
public void createDummyStage() {
    Stage dummyPopup = new Stage();
    dummyPopup.initModality(Modality.NONE);
    // set as utility so no iconification occurs
    dummyPopup.initStyle(StageStyle.UTILITY);
    // set opacity so the window cannot be seen
    dummyPopup.setOpacity(0d);
    // not necessary, but this will move the dummy stage off the screen
    final Screen screen = Screen.getPrimary();
    final Rectangle2D bounds = screen.getVisualBounds();
    dummyPopup.setX(bounds.getMaxX());
    dummyPopup.setY(bounds.getMaxY());
    // create/add a transparent scene
    final Group root = new Group();
    dummyPopup.setScene(new Scene(root, 1d, 1d, Color.TRANSPARENT));
    // show the dummy stage
    dummyPopup.show();
}
 @FXML
public void handleSysTryAction(ActionEvent event) {
    Stage stage = (Stage) button.getScene().getWindow();
    createDummyStage();
    stage.hide();
}
private void focusStage() {
    final Stage stage = (Stage) button.getScene().getWindow();
    if (!stage.isShowing()) {
        stage.show();
    }
    if (!stage.isFocused()) {
        stage.requestFocus();
    }
}