这是PostView的类定义,也是其fxml文件的控制器类。我正在尝试为一项名为 rogerbook 的大学作业(几个小时后到期,哈哈)制作一个 javaFX 社交媒体应用程序。此类扩展自 AnchorPane,因为它是要添加到用户的提要页面的 post 元素。每次我创建一个
new PostView();
时,它都会递归地调用相同的错误消息,LoadException如下:
at javafx.fxml@21/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2722)
at javafx.fxml@21/javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:946)
at javafx.fxml@21/javafx.fxml.FXMLLoader$RootElement.processAttribute(FXMLLoader.java:1302)
at javafx.fxml@21/javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:230)
at javafx.fxml@21/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:757)
at javafx.fxml@21/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2853)
at javafx.fxml@21/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2649)
at javafx.fxml@21/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2563)
at javafx.fxml@21/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2531)
at com.rogerbook.ui/com.rogerbook.ui.PostView.<init>(PostView.java:31)
然后它在 PostView 类中的所有实例变量上打印出另一个 NullPointerException。
这是类(减去导入):
package com.rogerbook.ui;
public class PostView extends AnchorPane {
PicPost post;
@FXML
private ImageView imageView = new ImageView();
@FXML
private Label Username = new Label();
@FXML
private Label Title = new Label();
public PostView(PicPost post){
this();
this.post = post;
initializePostView();
}
public PostView() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Post.fxml"));
fxmlLoader.setRoot(this);
try{
fxmlLoader.load();
}catch(IOException e){
e.printStackTrace();
}
}
private void initializePostView() {
if (post != null) {
imageView.setImage(post.getImage());
Username.setText(post.getAuthor().getProfile().getUserName());
Title.setText(post.getTitle());
}
}
}
该程序从注册页面开始。 这是运行程序启动的主要应用程序方法:
public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load());
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
注册时,其控制器类调用以下方法:
public class HelloController {
private Stage stage;
private Scene scene;
private Parent root;
@FXML
private TextField username;
@FXML
public TextField password;
@FXML
public TextField name;
@FXML
private TextField password2;
@FXML
private Label errmsg;
@FXML
public void switchToHome(ActionEvent event) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("scenefeedpage.fxml"));
stage = (Stage)((Node)event.getSource()).getScene().getWindow();
root = fxmlLoader.load();
scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
@FXML
public void onSignup(ActionEvent event) throws IOException {
System.out.println(password.getText());
if(password.getText().isEmpty() || username.getText().isEmpty() || name.getText().isEmpty() || password2.getText().isEmpty()){
errmsg.setText("Please fill all the fields");
return;
}
if(password.getText().equals(password2.getText())){
if(Roger.signup(username.getText().toLowerCase().strip(), password.getText())) {
switchToHome(event);
}
else {
errmsg.setText("Incorrect Password, or user does not exist");
}
}
else{
errmsg.setText("Passwords do not match");
}
}
}
注册按钮将用户重定向到 feed 页面,其中 feed 控制器将一些 PostView 组件添加到页面的 feed 区域(VBox):
public class FeedController implements Initializable {
private Stage stage;
private Scene scene;
private Parent root;
Post post;
@FXML
ImageView imageView;
@FXML
VBox view;
@Override
public void initialize(URL location, ResourceBundle resources) {
System.out.println("Initializing Feed");
ArrayList<Post> feed = Roger.getFeed();
System.out.println("Feed done");
feed.add(new PicPost("Hi", new Image("com/RogerBook/ui/R.png"), new User("maro", "aa")));
//PostView postView1 = new PostView((PicPost)feed.get(0));
post = feed.get(0);
view.getChildren().add(new PostView((PicPost)post));
//view.getChildren().add(new PostView());
}
public void ViewPost(ActionEvent event) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("Post.fxml"));
stage = (Stage)((Node)event.getSource()).getScene().getWindow();
root = fxmlLoader.load();
scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
我真的不知道现在该怎么办,我已经连续几个小时寻找解决方案并尝试了一切。请帮忙:D
修复
查看使用fx:root
方法的
FXML自定义控件的Oracle教程,它与您的代码不同。
fx:controller
属性。fxmlLoader.setController(this);
的调用,但您没有。我没有尝试你的代码来看看它是否适用于这些修复(这需要你的 FXML,但我没有)。但是,我假设如果您进行了这些修复,您的应用程序将按预期工作(没有其他错误)。
解释
如果您在 FXML 中提供控制器,而不是在代码中在 FXMLLoader 上设置控制器,则加载器将创建控制器的新实例,而不是使用现有实例。这可能就是您遇到空字段等问题的原因(FXMLLoader 将字段值注入到它创建的实例中,而不是您创建的实例中)。
您将进入递归循环,因为您在控制器构造函数中加载 FXML,而没有事先在加载器上设置控制器实例。然后加载器创建控制器的一个新实例,然后再次加载 FXML,然后创建一个新的控制器,依此类推。