JavaFX + Afterburner.fx从子进入父窗口

时间:2015-01-20 16:39:30

标签: java dependency-injection javafx

我有一个具有此窗口结构的程序:

enter image description here

左侧有按钮,绿色区域是不同的窗口,可以改变用户在左侧按钮上的位置。

我有一个主类(调用Estructura),它作为主窗口的控件,绿色面板除外。对于绿色面板,我从左侧注入(感谢afterburner.fx DI)对应面板基于用户按钮选择。由于基于MVP的DI Framework,注入的面板有自己的控制器是懒惰的。

public class EstructuraPresenter implements Initializable {

private static final Logger LOG = getLogger(EstructuraPresenter.class.getName());

@FXML
ToggleButton btnPlantillas, btnAlumnos, btnEstadisticas;
@FXML
BorderPane pEstructura; //Correspond to all window except green zone
@FXML 
StackPane pContenedor; //Green zone

//Injection of all child windows that i want to show in green zone
@Inject
private AlumnosView alumnosview;
@Inject
private PlantillasView plantillasview;
@Inject
private EstadisticasView estadisticasview;


@Override
public void initialize(URL url, ResourceBundle rb) {
    //I set up green zone with alumnos panel so I call method whit request section to load
    cambiarSeccion("Alumnos");

    btnPlantillas.setOnAction((ActionEvent event) -> {
        cambiarSeccion("Plantillas");
    });
    btnAlumnos.setOnAction((ActionEvent event) -> {
        cambiarSeccion("Alumnos");
    });
    btnEstadisticas.setOnAction((ActionEvent event) -> {
        cambiarSeccion("Estadisticas");
    });
}



//I pass to this method, name of window/panel that I like to load in green zone
public void cambiarSeccion(String nombreVentana) {
    try {
        //First, reset all buttons (so when user select an option and enter in case, I select option button making like effect as a selected)
        btnAlumnos.setSelected(false);
        btnPlantillas.setSelected(false);
        btnEstadisticas.setSelected(false);

        switch (nombreVentana) {
            case "Alumnos":
                if (btnAlumnos.isSelected() == false) {
                    sepTitulo.setVisible(true);
                    lbTitulo.setText("Alumnos");
                    btnAlumnos.setSelected(true);
                    //I need to do this check because for first time program load because green zone hasn't got any previous panel load 
                    if (pContenedor.getChildren().contains(alumnosview.getView())) {
                        pContenedor.getChildren().clear();
                        alumnosview.getViewAsync(pContenedor.getChildren()::add);
                    } else {
                        pContenedor.getChildren().add(alumnosview.getView());
                    }

                }
                break;
            case "Plantillas":
                if (btnPlantillas.isSelected() == false) {
                    sepTitulo.setVisible(true);
                    lbTitulo.setText("Plantillas");
                    btnPlantillas.setSelected(true);
                    pContenedor.getChildren().clear();
                    plantillasview.getViewAsync(pContenedor.getChildren()::add);
                }
                break;
            case "Estadisticas":
                if (btnEstadisticas.isSelected() == false) {
                    sepTitulo.setVisible(true);
                    lbTitulo.setText("Estadísticas");
                    btnEstadisticas.setSelected(true);
                    pContenedor.getChildren().clear();
                    estadisticasview.getViewAsync(pContenedor.getChildren()::add);
                }
                break;
            //There are more cases but I use same configuration like above examples...
        }
    }
    catch (Exception e) {
        LOG.log(Level.SEVERE, e.toString());
        new Dialogos().mostrarExcepcion(null, e);
    }
}
}

好吧,当左侧按钮上的用户clic时,面板在绿色区域中加载正常。但问题是我的用户例如在绿色区域clic上的按钮/链接...加载另一个面板(类似于上面的描述)但在这种情况下我需要从绿色面板控制器调用方法cambiarSeccion(),这是在EstructuraPresenter控制器中。

因此,例如,在用户选择estadisticas按钮的情况下(我隐藏在图像中,抱歉我试图简化),那就是estadisticaspresenter控制器:

public class EstadisticasPresenter implements Initializable {

    private static final Logger LOG = getLogger(EstadisticasPresenter.class.getName());

    @FXML
    Hyperlink linkTotalAlumnos;

    @Inject
    private EstructuraView estructuraview;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        linkTotalAlumnos.setOnAction((ActionEvent event) -> {
             //This call apparently works, I debug and call to method cambiarSeccion happend but screen isn't update
            ((EstructuraPresenter) estructuraview.getPresenter()).cambiarSeccion("Alumnos");
        });
    }
}

如果我加载了estadisticas窗口如果我单击左侧按钮,可以正常工作但是如果我在绿色加载面板上clic没有发生任何事情。我在下一张图片中恢复了问题: enter image description here

2 个答案:

答案 0 :(得分:1)

在我看来,你的方法有一个问题:当你打电话给任何一个孩子的主持人时

((EstructuraPresenter) estructuraview.getPresenter())
     .cambiarSeccion("Alumnos");

estructuraview.getPresenter()实际上是在创建主要演示者的新实例。

这意味着当您点击超链接时再次调用EstructuraPresenter.initialize(),并且您有两次调用cambiarSeccion()(一个来自Initialize,一个来自操作),孩子们到了新的实例,而不是旧的,这是你看到的那个。这就是为什么你没有看到任何变化!

我建议采用不同的方法:让主要演讲者听听孩子们某些属性的变化。

例如,添加一个布尔属性以通知单击超链接:

public class EstadisticasPresenter implements Initializable {

    @FXML Hyperlink linkTotalAlumnos;

    private final BooleanProperty link = new SimpleBooleanProperty();
    public boolean isLink() { return link.get(); }
    public void setLink(boolean value) { link.set(value); }
    public BooleanProperty linkProperty() { return link; }

    @Override public void initialize(URL url, ResourceBundle rb) {
        linkTotalAlumnos.setOnAction((ActionEvent event) -> {
            link.set(true);
        });
    }
}

在主要演讲者身上:

@Override
public void initialize(URL url, ResourceBundle rb) {

    ...

    EstadisticasPresenter estadisticas = 
        (EstadisticasPresenter)estadisticasview.getPresenter();

    estadisticas.linkProperty().addListener((ob,b,b1)->{
        if(b1){
            cambiarSeccion("Alumnos");
            // reset link property
            estadisticas.setLink(false);
        }
    });
}

作为旁注,我不是clear()add,而是使用pContenedor.getChildren().setAll(<view>);,因为您一次只展示一个孩子。

答案 1 :(得分:0)

基于@josé-pereda回答,最后我可以将子窗口(绿色区域)中的按钮/超链接链接到主控制器。我的解决方案的优点是我避免使用布尔变量。

EstructuraPresenter控制器中,我将监听器添加到EstadisticasPresenter(来自其中一个子窗口的控制器)的按钮中:

public class EstructuraPresenter implements Initializable {

    private static final Logger LOG = getLogger(EstructuraPresenter.class.getName());

    @FXML
    ToggleButton btnAlumnos, btnEstadisticas;
    @FXML
    StackPane pContenedor;

    @Inject
    private AlumnosView alumnosview;
    @Inject
    private EstadisticasView estadisticasview;
    @Inject
    private DataModel datos;

    @Override
    public void initialize(URL url, ResourceBundle rb) { 
        ((EstadisticasPresenter) estadisticasview.getPresenter()).getLinkTotalAlumnos().setOnAction((ActionEvent event) -> {
            this.cambiarSeccion("Alumnos");
        });

        //This call is from first time, where program starts to show by default Alumnos sub-window
        cambiarSeccion("Alumnos");

        btnAlumnos.setOnAction((ActionEvent event) -> {
            cambiarSeccion("Alumnos");
        });
        btnEstadisticas.setOnAction((ActionEvent event) -> {
            cambiarSeccion("Estadisticas");
        });
    }

    public void cambiarSeccion(String nombreVentana) {
        try {
            btnAlumnos.setSelected(false);
            btnEstadisticas.setSelected(false);

            switch (nombreVentana) {
                case "Alumnos":
                    if (btnAlumnos.isSelected() == false) {
                        sepTitulo.setVisible(true);
                        lbTitulo.setText("Alumnos");
                        btnAlumnos.setSelected(true);
                        alumnosview.getViewAsync(pContenedor.getChildren()::setAll);
                        pContenedor.getChildren().setAll(alumnosview.getView());
                    }
                    break;
                case "Estadisticas":
                    if (btnEstadisticas.isSelected() == false) {
                        sepTitulo.setVisible(true);
                        lbTitulo.setText("Estadísticas");
                        btnEstadisticas.setSelected(true);
                        estadisticasview.getViewAsync(pContenedor.getChildren()::setAll);
                    }
                    break;
            }
        }
        catch (Exception e) {
            LOG.log(Level.SEVERE, e.toString());
            new Dialogos().mostrarExcepcion(null, e);
        }
    }
}

注意此外,我更改了getChildren().clear()&amp;&amp; getChildren().add()getChildren().setAll();这些可以防止从我放入绿色区域的每个窗口重新初始化控制器。

estadisticasview.getViewAsync(pContenedor.getChildren():: SETALL);

在EstadisticasPresenter控制器中,我添加了来自该控件的getter,我想用户clic转到另一个窗口(所以当用户clic on control,绿色区域改变另一个窗口/窗格时)。

public class EstadisticasPresenter implements Initializable {

    private static final Logger LOG = getLogger(EstadisticasPresenter.class.getName());

    @FXML
    Hyperlink linkTotalAlumnos;

    @Inject
    private DataModel datamodel;

    @Override
    public void initialize(URL url, ResourceBundle rb) {

    }

    //Getters that I use in EstructuraPresenter controller to set up event handlers
    public Hyperlink getLinkTotalAlumnos() {
        return linkTotalAlumnos;
    }
}