controlsfx 是javaFx开源UI框架,里面有很多默认组件的补充,最近在使用其中的NotificationPane组件时,遇到一些问题,记录下来。
官方demo链接:
https://github.com/controlsfx/controlsfx/blob/jdk-8/controlsfx-samples/src/main/java/org/controlsfx/samples/HelloNotificationPane.javahttps://github.com/controlsfx/controlsfx/blob/jdk-8/controlsfx-samples/src/main/java/org/controlsfx/samples/HelloNotificationPane.java
NotificationPane 是一个通知组件,效果如图:
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);
}
}
实现效果如图:
由上面代码可以看出,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);
}
}
效果如图:
由图片发现,什么内容都没有,连定义的按钮组件都没有,经过仔细观察我们的组件并没有被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);
}
}
效果如图:
我们发现点击按钮不在有通知产生了。
通过上面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);
}
}
效果如图:
这次我们的根节点,同时添加了按钮组件和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);
}
}
效果如图:
从图中我们可以看到确实如预想的那样,根节点确实管理了由NotificationPane设置的组件。
此时我们可以总结一下NotificationPane与其他Pane类似都是一个布局组件,区别在于NotificationPane不管理子组件的相对位置,方向等,可以理解为一个空白且透明的布局组件,在使用时,需要注意要设置NotificationPane的显示位置,同时要将NotificationPane交由相对的根节点管理。
这两个缺一不可。