为什么在初始化后添加View会抛出NLP但不会在初始化期间使用afterburner.fx

时间:2017-09-11 15:43:04

标签: java javafx fxml

我正在使用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();
}
}

enter image description here

似乎我不了解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

1 个答案:

答案 0 :(得分:1)

Afterburner.fx是JavaFX的依赖注入框架。它提供的主要功能是能够将对象注入到加载FXML文件时创建的控制器/演示者中(通过实例化FXMLView的子类)。实例化FXMLView时发生的基本过程是:

  1. 创建相应演示者的新实例
  2. 检查演示者以查找任何@Inject - 带注释的字段
  3. 对于每个@Inject - 注释字段,如果注入器缓存中存在该类型的实例,则将其设置为该字段的值。否则,将创建该类型的新实例并将其放置在缓存中,并将其设置为字段的值。
  4. 这里要注意的要点是,演示者本身的处理方式与其依赖关系不同。如果您尝试(如在您的代码中)将一个演示者注入另一个演示者,将专门为注入目的创建一个演示者类的实例:这将不同于加载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());
                }
            });
        }      
    }