我正在使用afterburner.fx http://afterburner.adam-bien.com/
它像宣传的那样工作。我可以将多个fxml文件添加到中央/主要"视图"。
但是如果我想稍后添加另一个fxml / presenter,例如,使用不同navigationPane上的按钮将另一个fxml添加到mainAnchorPane。 然后它抛出NullPointerException。
public class MainscenePresenter implements Initializable {
@FXML
AnchorPane breadcrumbAnchor;
@FXML
AnchorPane navigationAnchor;
//--------------------------------------------------------
@FXML
private AnchorPane mainAnchorPane; //ADD NEW ATPANE HERE
private AtPresenter atPresenter;
private AtView atView;
//--------------------------------------------------------
@Override
public void initialize(URL url, ResourceBundle rb) {
//add BreadCrumBar WORKS
BreadcrumbbarView breadcrumbbarView = new BreadcrumbbarView();
breadcrumbbarView.getViewAsync(breadcrumbAnchor.getChildren()::add);
//add DFD WORKS
DfdView dfdView = new DfdView();
Parent view2 = dfdView.getView();
this.mainAnchorPane.getChildren().add(view2);
//add Navigation WORKS
NavigationView navigationView = new NavigationView();
Parent view = navigationView.getView();
navigationAnchor.getChildren().add(view);
//add AT
this.atView = new AtView();
this.atPresenter = (AtPresenter) this.atView.getPresenter();
//ADDING AT VIEW LIKE THIS WORKS <=========================
this.showAt();
}
void showAt() {
this.mainAnchorPane.getChildren().add(this.atView.getView()); // <== NLP here if invoked with buttonAt
}
public void buttonAt() {
//ADDING AT VIEW LIKE THIS(Button on different Presenter) DOES NOT WORK => NLP
this.showAt();
}
}
public class NavigationPresenter implements Initializable {
@FXML
Button atNavButton;
@Inject
MainscenePresenter mainscene;
private ResourceBundle resources = null;
@Override
public void initialize(URL location, ResourceBundle resources) {
this.resources = resources;
}
@FXML
void showDfdScene(ActionEvent event) {
mainscene.buttonAt();
}
}
似乎我不了解JavaFX的一些中心机制!无法命名,查找它!
为什么在这种情况下抛出NullPointerException而不是durin初始化?
Caused by: java.lang.NullPointerException
at abc.abc.app.mainscene.MainscenePresenter.showAt(MainscenePresenter.java:107)
at abc.abc.app.mainscene.MainscenePresenter.buttonAt(MainscenePresenter.java:112)
at abc.abc.app.navigation.NavigationPresenter.showDfdScene(NavigationPresenter.java:41)
... 58 more
答案 0 :(得分:1)
Afterburner.fx是JavaFX的依赖注入框架。它提供的主要功能是能够将对象注入到加载FXML文件时创建的控制器/演示者中(通过实例化FXMLView
的子类)。实例化FXMLView
时发生的基本过程是:
@Inject
- 带注释的字段@Inject
- 注释字段,如果注入器缓存中存在该类型的实例,则将其设置为该字段的值。否则,将创建该类型的新实例并将其放置在缓存中,并将其设置为字段的值。这里要注意的要点是,演示者本身的处理方式与其依赖关系不同。如果您尝试(如在您的代码中)将一个演示者注入另一个演示者,将专门为注入目的创建一个演示者类的实例:这将不同于加载FXML文件时创建的实例,因此它不会注入任何@FXML
个字段。这就是为什么你得到一个空指针异常:{`1}}在``MainScenePresenter mainAnchorPane
NavigationPresenter`中为空。
一位主持人提到另一位主持人通常是个坏主意:它会在两位主持人之间产生不必要的联系。相反,您应该将模型注入两个表示您想要在它们之间共享的状态的演示者。在你的情况下,你可能会有像
这样的东西that is injected into the
现在在演示者中,
public class ViewState {
private final BooleanProperty atShowing = new SimpleBooleanProperty();
public BooleanProperty atShowingProperty() {
return atShowing ;
}
public final boolean isAtShowing() {
return atShowingProperty().get();
}
public final void setAtShowing(boolean atShowing) {
atShowingProperty().set(atShowing);
}
}
和
public class MainscenePresenter implements Initializable {
@Inject
private ViewState viewState ;
@FXML
AnchorPane breadcrumbAnchor;
@FXML
AnchorPane navigationAnchor;
//------------------------------------------------------
@FXML
private AnchorPane mainAnchorPane; //ADD NEW ATPANE HERE
private AtPresenter atPresenter;
private AtView atView;
//------------------------------------------------------
@Override
public void initialize(URL url, ResourceBundle rb) {
//add BreadCrumBar WORKS
BreadcrumbbarView breadcrumbbarView = new BreadcrumbbarView();
breadcrumbbarView.getViewAsync(breadcrumbAnchor.getChildren()::add);
//add DFD WORKS
DfdView dfdView = new DfdView();
Parent view2 = dfdView.getView();
this.mainAnchorPane.getChildren().add(view2);
//add Navigation WORKS
NavigationView navigationView = new NavigationView();
Parent view = navigationView.getView();
navigationAnchor.getChildren().add(view);
//add AT
this.atView = new AtView();
this.atPresenter = (AtPresenter) this.atView.getPresenter();
this.viewState.atShowingProperty().addListener((obs, wasShowing, isNowShowing) -> {
if (isNowShowing) {
this.mainAnchorPane.getChildren().remove(this.atView.getView());
} else {
this.mainAnchorPane.getChildren().add(this.atView.getView());
}
});
}
}