带有controlsfx通知组件的javafx NullPointerException

2023-12-14

我想开发一个使用controlsfx通知在系统托盘模式下显示一些通知的应用程序。在正常模式下,我的应用程序运行良好,并且可以成功显示通知。但是当我在系统托盘中隐藏阶段时,会发生 NullPointerException。我不知道如何解决这个问题。

import java.awt.AWTException;
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 javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

public class TryIconNotification extends Application {
    private boolean firstTime;
    private TrayIcon trayIcon;

    @Override
    public void start(Stage stage) throws Exception {
        firstTime = true;
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

        Scene scene = new Scene(root);

        createTrayIcon(stage);
        firstTime = true;
        Platform.setImplicitExit(false);

        stage.setScene(scene);
        stage.show();
    }

    public void createTrayIcon(final Stage stage) {
        if (SystemTray.isSupported()) {
            // get the SystemTray instance
            SystemTray tray = SystemTray.getSystemTray();
            // load an image
            java.awt.Image image = null;
            image = Toolkit.getDefaultToolkit().getImage("icons\\iconify.png");

            stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
                @Override
                public void handle(WindowEvent t) {
                    hide(stage);
                }
            });

            // create a action listener to listen for default action executed on the tray icon
            final ActionListener closeListener = new ActionListener() {
                @Override
                public void actionPerformed(java.awt.event.ActionEvent e) {
                    stage.hide();

                }
            };

            ActionListener showListener = new ActionListener() {
                @Override
                public void actionPerformed(java.awt.event.ActionEvent e) {
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            stage.show();
                        }
                    });
                }
            };
            // create a popup menu
            PopupMenu popup = new PopupMenu();

            MenuItem showItem = new MenuItem("Open app");

            showItem.addActionListener(showListener);
            popup.add(showItem);

            MenuItem closeItem = new MenuItem("Exit");
            closeItem.addActionListener(closeListener);
            popup.add(closeItem);
            /// ... add other items
            // construct a TrayIcon
            trayIcon = new TrayIcon(image, "Systray", popup);
            // set the TrayIcon properties
            trayIcon.addActionListener(showListener);
            // ...
            // add the tray image
            try {
                tray.add(trayIcon);
            } catch (AWTException e) {
                System.err.println(e);
            }
            // ...
        }
    }

    public void showProgramIsMinimizedMsg() {
        //only in first time show the message
        if (firstTime) {
            trayIcon.displayMessage("System Tray",
                    "Iconified",
                    TrayIcon.MessageType.INFO);
            firstTime = false;
        }
    }

    private void hide(final Stage stage) {
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                if (SystemTray.isSupported()) {
                    stage.hide();
                    showProgramIsMinimizedMsg();
                } else {
                    System.exit(0);
                    System.out.println("Not Support Sys Tray");
                }
            }
        });
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}

这是我的控制器类:

import java.net.URL;
import java.util.ResourceBundle;
import java.util.Timer;
import java.util.TimerTask;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import org.controlsfx.control.Notifications;

public class FXMLDocumentController  implements Initializable   {

    @FXML
    private Label label;

    @FXML
    private void handleButtonAction(ActionEvent event) {
        Stage stage = (Stage) label.getScene().getWindow();
        stage.hide();
    }

    public void createNotification() {
        Notifications.create()
                .text("This is a Notification")
                .title("Notifications")
                .showInformation();
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        Timer timer = new Timer();

        timer.scheduleAtFixedRate(new TimerTask() {

            @Override
            public void run() {
              Platform.runLater(()->createNotification());
            }

        }, 5000, 10000);
    }
}

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

解决方案一:

打开舞台并显示通知。 这样我们应该检查舞台是否被隐藏,打开它并显示通知。 为此,我们必须在 CreateNotification 方法中添加此条件:

Stage stage = (Stage)  button.getScene().getWindow();
if (!stage.isShowing()){
    stage.show();
}

解决方案2:

在此解决方案中,我们创建一个虚拟舞台并将其不透明度设置为零,然后隐藏主舞台。我在此链接中找到此解决方案并将代码放入here:

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();
}

我实现了这两个解决方案,一切都运行良好。如果您对这个问题有更好的解决方案请放在这里

您可以从我的网站下载完整的 Netbeans 项目Dropbox

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有controlsfx通知组件的javafx NullPointerException 的相关文章

  • 如何将本机库链接到 IntelliJ 中的 jar?

    我正在尝试在 IntelliJ 中设置 OpenCV 但是我一直在弄清楚如何告诉 IntelliJ 在哪里可以找到本机库位置 在 Eclipse 中 添加 jar 后 您可以在 Build Config 屏幕中设置 Native 库的位置
  • 为什么 JTables 使 TableModel 在呈现时不可序列化?

    所以最近我正在开发一个工具 供我们配置某些应用程序 它不需要是什么真正令人敬畏的东西 只是一个具有一些 SQL 脚本生成功能并创建几个 XML 文件的基本工具 在此期间 我使用自己的 AbstractTableModel 实现创建了一系列
  • 使用 LinkedList 实现下一个和上一个按钮

    这可能是一个愚蠢的问题 但我很难思考清楚 我编写了一个使用 LinkedList 来移动加载的 MIDI 乐器的方法 我想制作一个下一个和一个上一个按钮 以便每次单击该按钮时都会遍历 LinkedList 如果我硬编码itr next or
  • 为 java 游戏创建交互式 GUI

    大家好 我正在创建一个类似于 java 中的 farmville 的游戏 我只是想知道如何实现用户通常单击以与游戏客户端交互的交互式对象 按钮 我不想使用 swing 库 通用 Windows 看起来像对象 我想为我的按钮导入自定义图像 并
  • 如何使用assertEquals 和 Epsilon 在 JUnit 中断言两个双精度数?

    不推荐使用双打的assertEquals 我发现应该使用带有Epsilon的形式 这是因为双打不可能100 严格 但无论如何我需要比较两个双打 预期结果和实际结果 但我不知道该怎么做 目前我的测试如下 Test public void te
  • Pig Udf 显示结果

    我是 Pig 的新手 我用 Java 编写了一个 udf 并且包含了一个 System out println 其中的声明 我必须知道在 Pig 中运行时该语句在哪里打印 假设你的UDF 扩展了 EvalFunc 您可以使用从返回的 Log
  • 将 MOXy 设置为 JAXB 提供程序,而在同一包中没有属性文件

    我正在尝试使用 MOXy 作为我的 JAXB 提供程序 以便将内容编组 解组到 XML JSON 中 我创建了 jaxb properties 文件 内容如下 javax xml bind context factory org eclip
  • volatile、final 和synchronized 安全发布的区别

    给定一个带有变量 x 的 A 类 变量 x 在类构造函数中设置 A x 77 我们想将 x 发布到其他线程 考虑以下 3 种变量 x 线程安全 发布的情况 1 x is final 2 x is volatile 3 x 设定为同步块 sy
  • 当 OnFocusChangeListener 应用于包装的 EditText 时,TextInputLayout 没有动画

    不能比标题说得更清楚了 我有一个由文本输入布局包裹的 EditText 我试图在 EditText 失去焦点时触发一个事件 但是 一旦应用了事件侦听器 TextInputLayout 就不再对文本进行动画处理 它只是位于 editText
  • tomcat 中受密码保护的应用程序

    我正在使用 JSP Servlet 开发一个Web应用程序 并且我使用了Tomcat 7 0 33 as a web container 所以我的要求是tomcat中的每个应用程序都会password像受保护的manager applica
  • 如何在谷歌地图android上显示多个标记

    我想在谷歌地图android上显示带有多个标记的位置 问题是当我运行我的应用程序时 它只显示一个位置 标记 这是我的代码 public class koordinatTask extends AsyncTask
  • Java 和 Python 可以在同一个应用程序中共存吗?

    我需要一个 Java 实例直接从 Python 实例数据存储中获取数据 我不知道这是否可能 数据存储是否透明 唯一 或者每个实例 如果它们确实可以共存 都有其单独的数据存储 总结一下 Java 应用程序如何从 Python 应用程序的数据存
  • java for windows 中的文件图标叠加

    我正在尝试像 Tortoise SVN 或 Dropbox 一样在文件和文件夹上实现图标叠加 我在网上查了很多资料 但没有找到Java的解决方案 Can anyone help me with this 很抱歉确认您的担忧 但这无法在 Ja
  • Eclipse 选项卡宽度不变

    我浏览了一些与此相关的帖子 但它们似乎并不能帮助我解决我的问题 我有一个项目 其中 java 文件以 2 个空格的宽度缩进 我想将所有内容更改为 4 空格宽度 我尝试了 正确的缩进 选项 但当我将几行修改为 4 空格缩进时 它只是将所有内容
  • 使用 AsyncTask 传递值

    我一直在努力解决这个问题 但我已经到了不知道该怎么办的地步 我想做的是使用一个类下载文件并将其解析为字符串 然后将该字符串发送到另一个类来解析 JSON 内容 所有部件都可以单独工作 并且我已经单独测试了所有部件 我只是不知道如何将值发送到
  • 不接受任何内容也不返回任何内容的函数接口[重复]

    这个问题在这里已经有答案了 JDK中是否有一个标准的函数式接口 不接受也不返回任何内容 我找不到一个 像下面这样 FunctionalInterface interface Action void execute 可运行怎么样 Functi
  • Eclipse 启动时崩溃;退出代码=13

    I am trying to work with Eclipse Helios on my x64 machine Im pretty sure now that this problem could occur with any ecli
  • Opencv Java 灰度

    我编写了以下程序 尝试从彩色转换为灰度 Mat newImage Imgcodecs imread q1 jpg Mat image new Mat new Size newImage cols newImage rows CvType C
  • 找不到符号 NOTIFICATION_SERVICE?

    package com test app import android app Notification import android app NotificationManager import android app PendingIn
  • 在java中为组合框分配键

    我想添加一个JComboBox在 Swing 中这很简单 但我想为组合中的每个项目分配值 我有以下代码 JComboBox jc1 new JComboBox jc1 addItem a jc1 addItem b jc1 addItem

随机推荐