controlsfx 是javaFx开源UI框架,里面有很多默认组件的补充,最近在使用其中的NotificationPane组件时,遇到一些问题,记录下来。

官方demo链接:

https://github.com/controlsfx/controlsfx/blob/jdk-8/controlsfx-samples/src/main/java/org/controlsfx/samples/HelloNotificationPane.java

javaFX alert显示中文失败 javafx弹出提示框_github

https://github.com/controlsfx/controlsfx/blob/jdk-8/controlsfx-samples/src/main/java/org/controlsfx/samples/HelloNotificationPane.java

NotificationPane 是一个通知组件,效果如图:

javaFX alert显示中文失败 javafx弹出提示框_ide_02

controlsfx框架中还有一个通知组件是:Notifications,显示效果是从桌面边缘(8个方向)及中间弹出通知 (用法比较简单,就不多说了)。相比较于NotificationPane,NotificationPane更专注于当前操作,而Notifications适用于非重要的消息通知

这里按照官方的Demo做一个测试。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.SplitPane;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest1 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest1");
        SplitPane splitPane = new SplitPane();
        Button button = new Button("通知按钮");
        NotificationPane notificationPane = new NotificationPane();
        button.setOnAction(event -> {
            notificationPane.setText("这个是NotificationPane的通知");
            notificationPane.show();
        });
//        这里与NotificationPane notificationPane = new NotificationPane(button);效果一致,指定通知显示位置
        notificationPane.setContent(button);
        splitPane.getItems().add(notificationPane);
        Scene scene = new Scene(splitPane);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

实现效果如图:

javaFX alert显示中文失败 javafx弹出提示框_ui_03

由上面代码可以看出,notificationPane.setContent() 代码用来设置通知显示位置,并且显示的通知覆盖了定义的按钮组件。

那么如果不设置通知的显示位置会发生什么。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.SplitPane;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest2 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest2");
        SplitPane splitPane = new SplitPane();
        Button button = new Button("通知按钮");
        NotificationPane notificationPane = new NotificationPane();
        button.setOnAction(event -> {
            notificationPane.setText("这个是NotificationPane的通知");
            notificationPane.show();
        });
        splitPane.getItems().add(notificationPane);
        Scene scene = new Scene(splitPane);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

效果如图:

javaFX alert显示中文失败 javafx弹出提示框_github_04

由图片发现,什么内容都没有,连定义的按钮组件都没有,经过仔细观察我们的组件并没有被SpliPane(根Node管理),那么我们让根节点管理我们的按钮组件,看会发生什么。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.SplitPane;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest3 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest3");
        SplitPane splitPane = new SplitPane();
        Button button = new Button("通知按钮");
        NotificationPane notificationPane = new NotificationPane();
        button.setOnAction(event -> {
            notificationPane.setText("这个是NotificationPane的通知");
            notificationPane.show();
        });

        splitPane.getItems().add(button);
        Scene scene = new Scene(splitPane);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

效果如图:

javaFX alert显示中文失败 javafx弹出提示框_ide_05

我们发现点击按钮不在有通知产生了。

 通过上面3处代码,及实验结果我们发现:

代码1:NotificationPane设置了通知显示位置,且根节点管理了NotificationPane,结果显示正常

代码2:NotificationPane未设置通知显示位置,且根节点管理了NotificationPane,结果什么都没有显示

代码3:NotificationPane未设置通知显示位置,而根节点管理了按钮组件,结果点击按钮无通知

此时我们知道,如果想要实现通知显示,必须满足两个条件:

1.定义通知显示位置

2.通知组件要被根节点管理

有了上面两个经验,我们看看下面的代码:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest4 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest4");
        SplitPane splitPane = new SplitPane();
        Button button = new Button("通知按钮");
//        随便定义一个组件,只用来显示通知
        VBox vBox = new VBox();
        NotificationPane notificationPane = new NotificationPane(vBox);
        button.setOnAction(event -> {
            notificationPane.setText("这个是NotificationPane的通知");
            notificationPane.show();
        });

        splitPane.getItems().add(button);
        splitPane.getItems().add(notificationPane);
        Scene scene = new Scene(splitPane);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

效果如图:

javaFX alert显示中文失败 javafx弹出提示框_ui_06

这次我们的根节点,同时添加了按钮组件和NotificationPane通知组件,而通知组件则显示在一个空的VBox组件上,同样也实现了通知效果,虽然在我编写的代码里根节点并没有管理那个空的VBox,但是由于NotificationPane通知组件设置在了VBox上,我们也可以看到,实际上根节点也是添加了这个VBox,为了更直观的看到效果,我们对代码稍作改动。

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest5 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest5");
        SplitPane splitPane = new SplitPane();
        Button button = new Button("通知按钮");
//        随便定义一个组件,只用来显示通知
        VBox vBox = new VBox();
        Label label = new Label("如果根节点未管理VBox,你就看不到我");
        vBox.setAlignment(Pos.CENTER);
        vBox.getChildren().add(label);
        NotificationPane notificationPane = new NotificationPane(vBox);
        button.setOnAction(event -> {
            notificationPane.setText("这个是NotificationPane的通知");
            notificationPane.show();
        });

        splitPane.getItems().add(button);
        splitPane.getItems().add(notificationPane);
        Scene scene = new Scene(splitPane);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

效果如图:

javaFX alert显示中文失败 javafx弹出提示框_java_07

从图中我们可以看到确实如预想的那样,根节点确实管理了由NotificationPane设置的组件。

此时我们可以总结一下NotificationPane与其他Pane类似都是一个布局组件,区别在于NotificationPane不管理子组件的相对位置,方向等,可以理解为一个空白且透明的布局组件,在使用时,需要注意要设置NotificationPane的显示位置,同时要将NotificationPane交由相对的根节点管理。

这两个缺一不可。

最后还有三个点需要注意:

1.NotificationPane.setContent()设置显示位置时,最好不要设置为空的布局组件,否则可能无法显示,但是在某些布局中可以显示如SplitPane

2.NotificationPane.show()方法在构造方法中无效

3.在使用NotificationPane.show()方法时,应先判断当前NotificationPane的状态是否是显示,如果是显示状态,则应先hide(),再进行show()

我们将用代码来验证以上三点:

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest6 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest6");
        VBox root = new VBox();
        Button button = new Button("通知按钮");
        root.setAlignment(Pos.CENTER);
//        随便定义一个空Pane,只用来显示通知
        VBox content = new VBox();
        NotificationPane notificationPane = new NotificationPane(content);
        notificationPane.setText("这个是NotificationPane的通知");
        button.setOnAction(event -> {
            notificationPane.show();
        });
        root.getChildren().addAll(button,notificationPane);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

显示效果:

javaFX alert显示中文失败 javafx弹出提示框_github_08

从图中可以看到点击按钮,没有通知产生。那么我们跟content中添加些组件试一试

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest7 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest7");
        VBox root = new VBox();
        Button button = new Button("通知按钮");
        root.setAlignment(Pos.CENTER);
        VBox content = new VBox();
//        这次往conten中塞入一个Label
        content.getChildren().add(new Label());
        NotificationPane notificationPane = new NotificationPane(content);
        notificationPane.setText("这个是NotificationPane的通知");
        button.setOnAction(event -> {
            notificationPane.show();
        });
        root.getChildren().addAll(button,notificationPane);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

显示效果:

javaFX alert显示中文失败 javafx弹出提示框_javaFX alert显示中文失败_09

 可以看出在如果通知组件的显示位置设置在了空的布局组件中时,通知不会弹出,验证了第一点

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest8 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest8");
        AnchorPane anchorPane = new AnchorPane();
        Button button = new Button("通知按钮");
        AnchorPane.setBottomAnchor(button, 300.0);
        AnchorPane.setTopAnchor(button, 300.0);
        AnchorPane.setLeftAnchor(button, 150.0);
        AnchorPane.setRightAnchor(button, 150.0);
        anchorPane.getChildren().add(button);

        button.setOnAction(event -> {
            Dialog<Object> dialog = new Dialog<>();
            DialogPane dialogPane = dialog.getDialogPane();
            MyDialog myDialog = new MyDialog();
            dialogPane.setContent(myDialog);
            ObservableList<ButtonType> buttonTypes = dialogPane.getButtonTypes();
            buttonTypes.addAll(ButtonType.APPLY);
            dialog.show();
        });
        Scene scene = new Scene(anchorPane);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }


    class MyDialog extends VBox {
        NotificationPane notificationPane = new NotificationPane();
        public MyDialog() {
            setPrefWidth(150);
            setPrefHeight(200);
            VBox vBox = new VBox();
            Button button = new Button("我就是个填充空布局的组件");
            vBox.getChildren().add(button);
            notificationPane.setContent(vBox);
            notificationPane.setText("这个是NotificationPane的通知");
            getChildren().add(notificationPane);
//            构造方法中开启显示
            notificationPane.show();

        }
    }


}

效果如图:

 

javaFX alert显示中文失败 javafx弹出提示框_ui_10

上面代码,我把NotificationPane.show()方法直接定义在了我们自定义Dialog的构造方法了里,结果发现通知组件并没有显示。

这里我们做一个猜想,之所以没有显示通知是不是自定的Dilog还没有实例化完成呢?因此这里我们做一点小改动,让show()方法异步执行。

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest8 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest8");
        AnchorPane anchorPane = new AnchorPane();
        Button button = new Button("通知按钮");
        AnchorPane.setBottomAnchor(button, 300.0);
        AnchorPane.setTopAnchor(button, 300.0);
        AnchorPane.setLeftAnchor(button, 150.0);
        AnchorPane.setRightAnchor(button, 150.0);
        anchorPane.getChildren().add(button);

        button.setOnAction(event -> {
            Dialog<Object> dialog = new Dialog<>();
            DialogPane dialogPane = dialog.getDialogPane();
            MyDialog myDialog = new MyDialog();
            dialogPane.setContent(myDialog);
            ObservableList<ButtonType> buttonTypes = dialogPane.getButtonTypes();
            buttonTypes.addAll(ButtonType.APPLY);
            dialog.show();
        });
        Scene scene = new Scene(anchorPane);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }


    class MyDialog extends VBox {
        NotificationPane notificationPane = new NotificationPane();
        public MyDialog() {
            setPrefWidth(150);
            setPrefHeight(200);
            VBox vBox = new VBox();
            Button button = new Button("我就是个填充空布局的组件");
            vBox.getChildren().add(button);
            notificationPane.setContent(vBox);
            notificationPane.setText("这个是NotificationPane的通知");
            getChildren().add(notificationPane);
//            构造方法中异步开启显示
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    notificationPane.show();
                }
            });
        }
    }
}

显示效果如下:

javaFX alert显示中文失败 javafx弹出提示框_ide_11

我们发现在构造方法里异步执行show()方法也是可行的,但是并不推荐这么做,如果是dialog的场景,其实可以添加dialog的时间,在dialog显示后,调用show()方法,推荐的写法如下:

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest8 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest8");
        AnchorPane anchorPane = new AnchorPane();
        Button button = new Button("通知按钮");
        AnchorPane.setBottomAnchor(button, 300.0);
        AnchorPane.setTopAnchor(button, 300.0);
        AnchorPane.setLeftAnchor(button, 150.0);
        AnchorPane.setRightAnchor(button, 150.0);
        anchorPane.getChildren().add(button);

        button.setOnAction(event -> {
            Dialog<Object> dialog = new Dialog<>();
            DialogPane dialogPane = dialog.getDialogPane();
            MyDialog myDialog = new MyDialog();
            dialogPane.setContent(myDialog);
            ObservableList<ButtonType> buttonTypes = dialogPane.getButtonTypes();
            buttonTypes.addAll(ButtonType.APPLY);
//            dialog显示完成后执行,注意需要写在dialog.show()之前,否则不生效
            dialog.setOnShown(e -> {
                myDialog.show();
            });
            dialog.show();
        });
        Scene scene = new Scene(anchorPane);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }


    class MyDialog extends VBox {
        NotificationPane notificationPane = new NotificationPane();

        public MyDialog() {
            setPrefWidth(150);
            setPrefHeight(200);
            VBox vBox = new VBox();
            Button button = new Button("我就是个填充空布局的组件");
            vBox.getChildren().add(button);
            notificationPane.setContent(vBox);
            notificationPane.setText("这个是NotificationPane的通知");
            getChildren().add(notificationPane);
        }

        public void show() {
            notificationPane.show();
        }
    }
}

以上就验证了第二点。

验证第三点需要写一些错误代码:

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest9 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest9");
        AnchorPane anchorPane = new AnchorPane();
        Button button = new Button("通知按钮");
        AnchorPane.setBottomAnchor(button, 300.0);
        AnchorPane.setTopAnchor(button, 300.0);
        AnchorPane.setLeftAnchor(button, 150.0);
        AnchorPane.setRightAnchor(button, 150.0);
        anchorPane.getChildren().add(button);

        
        button.setOnAction(event -> {
            Dialog<Object> dialog = new Dialog<>();
            MyDialog myDialog = new MyDialog();
            DialogPane dialogPane = dialog.getDialogPane();
            ObservableList<ButtonType> buttonTypes = dialogPane.getButtonTypes();
            buttonTypes.addAll(ButtonType.APPLY);
            dialogPane.setContent(myDialog);
//           1.开启了通知显示操作
            dialog.setOnShown(e -> {
                myDialog.show();
            });
            dialog.show();
        });
        Scene scene = new Scene(anchorPane);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }


    class MyDialog extends VBox {
        NotificationPane notificationPane = new NotificationPane();
        public MyDialog() {
            setPrefWidth(150);
            setPrefHeight(200);
            VBox vBox = new VBox();
            Button button = new Button("这是一个随便的按钮");
            vBox.getChildren().add(button);
            notificationPane.setContent(vBox);
            notificationPane.setText("这个是NotificationPane的通知");
            getChildren().add(notificationPane);
//            2.开启了通知显示操作
            notificationPane.show();
        }
        public void show(){
            notificationPane.show();
        }
    }
}

效果如图:

javaFX alert显示中文失败 javafx弹出提示框_ui_12

这里看到通知组件并没有弹出,而我们的代码里也写了两处show(),如果说构造方法中的show()方法不显示的话,可以说的通,毕竟之前也实验过了,但是在dilog.setOnShown()中也设置了show(),此时应该显示通知才对的。

我们更改下代码:

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest10 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest10");
        AnchorPane anchorPane = new AnchorPane();
        Button button = new Button("通知按钮");
        AnchorPane.setBottomAnchor(button, 300.0);
        AnchorPane.setTopAnchor(button, 300.0);
        AnchorPane.setLeftAnchor(button, 150.0);
        AnchorPane.setRightAnchor(button, 150.0);
        anchorPane.getChildren().add(button);

        button.setOnAction(event -> {
            Dialog<Object> dialog = new Dialog<>();
            MyDialog myDialog = new MyDialog();
            DialogPane dialogPane = dialog.getDialogPane();
            ObservableList<ButtonType> buttonTypes = dialogPane.getButtonTypes();
            buttonTypes.addAll(ButtonType.APPLY);
            dialogPane.setContent(myDialog);
            dialog.setOnShown(e -> {
                myDialog.show();
            });
            dialog.show();
        });
        Scene scene = new Scene(anchorPane);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }


    class MyDialog extends VBox {
        NotificationPane notificationPane = new NotificationPane();
        Label label = new Label();

        public MyDialog() {
            setPrefWidth(150);
            setPrefHeight(200);
            VBox vBox = new VBox();
//            设置子组件间距
            vBox.setSpacing(20);
            Button button = new Button("这是一个随便的按钮");
            vBox.getChildren().add(button);
            label.setText("通知状态是:false");
            vBox.getChildren().add(label);
            notificationPane.setContent(vBox);
            notificationPane.setText("这个是NotificationPane的通知");
            getChildren().add(notificationPane);
            notificationPane.show();
        }

        public void show() {
            if (notificationPane.isShowing()) {
                label.setText("111111");
                notificationPane.hide();
                notificationPane.show();
            } else {
                label.setText("2222");
                notificationPane.show();
            }
        }
    }
    
}

这里我们加了一个Label用来表示状态,如果当前已经是显示状态,则label显示为1111,否则为2222

效果如图:

javaFX alert显示中文失败 javafx弹出提示框_ide_13

可以看出当前通知状态是showing 

此时我们将构造方法里show()方法去掉看一下结果:

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.NotificationPane;


public class NotificationPaneTest10 extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("NotificationPaneTest10");
        AnchorPane anchorPane = new AnchorPane();
        Button button = new Button("通知按钮");
        AnchorPane.setBottomAnchor(button, 300.0);
        AnchorPane.setTopAnchor(button, 300.0);
        AnchorPane.setLeftAnchor(button, 150.0);
        AnchorPane.setRightAnchor(button, 150.0);
        anchorPane.getChildren().add(button);

        button.setOnAction(event -> {
            Dialog<Object> dialog = new Dialog<>();
            MyDialog myDialog = new MyDialog();
            DialogPane dialogPane = dialog.getDialogPane();
            ObservableList<ButtonType> buttonTypes = dialogPane.getButtonTypes();
            buttonTypes.addAll(ButtonType.APPLY);
            dialogPane.setContent(myDialog);
            dialog.setOnShown(e -> {
                myDialog.show();
            });
            dialog.show();
        });
        Scene scene = new Scene(anchorPane);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }


    class MyDialog extends VBox {
        NotificationPane notificationPane = new NotificationPane();
        Label label = new Label();

        public MyDialog() {
            setPrefWidth(150);
            setPrefHeight(200);
            VBox vBox = new VBox();
//            设置子组件间距
            vBox.setSpacing(20);
            Button button = new Button("这是一个随便的按钮");
            vBox.getChildren().add(button);
            label.setText("通知状态是:false");
            vBox.getChildren().add(label);
            notificationPane.setContent(vBox);
            notificationPane.setText("这个是NotificationPane的通知");
            getChildren().add(notificationPane);
        }

        public void show() {
            if (notificationPane.isShowing()) {
                label.setText("111111");
                notificationPane.hide();
                notificationPane.show();
            } else {
                label.setText("2222");
                notificationPane.show();
            }
        }
    }

}

效果如图:

javaFX alert显示中文失败 javafx弹出提示框_ui_14

可以看到这次label的状态是2222,通知是hide状态,这就验证了第三点

由此需要知道当 调用NotificationPane.show()方法时,是会更改NotificationPane的状态的,而更改了NotificationPane的状态并不代表NotificationPane会显示,所以在NotificationPane的状态是showing时,再次调用NotificationPane.show()方法,NotificationPane是不会显示的,需要先调用

NotificationPane.hide()方法,再调用NotificationPane.show()方法