1. FXMLLoader.load() 问题
具体代码如下:
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("login.fxml"));
stage.setScene(new Scene(root, 580, 400));
stage.show();
}
具体项目结构如图所示:
可以看见就是很简单的读取fxml文件,然后展示即可。
结果,我遇到了空指针异常,提示无法找到对于文件,于是乎我根据网上教程各种修改,大概有以下几种方式:
//方法一
Parent root = FXMLLoader.load(getClass().getResource("/login.fxml"));
//方法二
Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("login.fxml"));
//方法三
Parent root = FXMLLoader.load(getClass().getResource("/fxml/login.fxml"));
//....等等基本上网上的路径我都试过了
最后看了这篇文章解决了:Maven + Java FX出现问题:Caused by: java.lang.NullPointerException: Location is required.
修改后应该为:
Parent root = FXMLLoader.load(getClass().getResource("/static/fxml/login.fxml"));
其实是因为编译后,项目实际运行时会从target目录中读取文件,所以路径应该对应target中的具体路径。
在修改过程中,我觉得自己就在正确的大门旁边,最后改正确也挺开心的,不过这个错误确实很小,但真的很难改(因为是初学菜鸟罢了)。
2.FXML中定义组件在Controller中如何进行绑定并进行后续操作。
学习过程中,发现定义JavaFx中组件的方式主要有两种,以新建Button为例
① 在java文件中进行定义,如下:
VBox hbox = new VBox();
Button add = new Button("添加");
add.setOnAction(new EventHandler<ActionEvent>(){
public void handle(ActionEvent event) {
//进行相对应操作
}
});
hbox.getChildren().addAll(add); //将按钮加入VBox布局中
②在FXML文件中进行定义,如下:
<HBox alignment="bottom_right" spacing="10" GridPane.columnIndex="1" GridPane.rowIndex="4">
<JFXButton fx:id="btnlogin" onAction="#loginButtonAction" buttonType="RAISED" text="登录" />
</HBox>
对应按钮的Action可以在对应的Controller中定义。
在实际开发中我选择了第二种方法,来添加需要的组件,然后在Controller定义相应的Action,但是接下来我在实际应用中就遇到了一个问题:
以设置一个Label值为例,我在FXML中定义一个Label,希望能够再点击Button之后,Label显示相应的文本,例如“Click!”等,一切都很顺畅,我在FXML文件中定义Label和Button组件,指定相应的Controller,然后编写Controller代码,当我完成之后,点击运行时,却无法运行,提示如下:
Label对象并未初始化。
之后,我尝试过在Controller层代码中,对该Label对象进行新建,这个报错的确消失了,但是点击按钮之后,页面上的Label并没有显示出对应的值。
最终,在我尝试了各种关键字搜索解决办法之后,我找到了解决办法。
办法如下:
//FXML层代码:
<Label fx:id="id" />
<JFXButton fx:id="btn" onAction="#loginButtonAction" buttonType="RAISED" text="点击" />
//Controller层代码:(仅展示关键代码)
@FXML
Label id;
///省略
id= (Label) root.lookup("#id");//绑定
///省略
绑定完成之后,就可以执行id.setText("Click !");语句,并且成功再点击按钮之后显示文本。
所以如果在FXML中定义组件之后,不仅需要在Controller层声明该组件,还需要在使用之前对组件进行绑定操作,之后才能进行后续操作。