简体   繁体   中英

JavaFX. Dynamic Accordion

I have JavaFX project where fxml and code are used to make a GUI.

There is a GUI: 在此处输入图片说明 在此处输入图片说明

As you can see there are 2 JavaFX.TitledPane . They are created in a fxml. After them, i have a JavaFX.Accordion . I get number of pipes from JavaFX.TextField and generate them. There are some different type of JavaFX.TitledPane which are put into Accordion. You can see different type on screenshots.

I have a problem: Each TitledPane in the Accordion have the first ChoiceBox. This ChoiceBox defines the type of TitledPane. So we have default TitledPane on #1 screenshot. When user choose another item from the ComboBox, we need to recreate the TitledPane. Moreover we need to save data inside the TitledPane's text boxes and restore it inside new TitledPane. Please, give me advice or part of the code, which can solve this problem in right way.

I have such Controller class:

public class Controller {

@FXML
TextField textFieldNonConservatismCoef;
@FXML
TextField textFieldDiffusionCoef;
@FXML
TextField textFieldFlowSpeed;
@FXML
TextField textFieldRiverDepth;
@FXML
TextField textFieldRiverWidth;
@FXML
TextField textFieldSubstance;
@FXML
TextField textFieldProportion;
@FXML
TextField textFieldLAC;
@FXML
TextField textFieldConcentration;
@FXML
TextField textFieldNumberOfPipes;
@FXML
Accordion accordionPlant;





public void fillAccordion(int numberOfPipes){

    accordionPlant.getPanes().add(createTitledPaneCoastalConcentratedPipe(0));
    accordionPlant.getPanes().add(createTitledPaneCoastalSpreadPipe(1));

}

//Create the first type of a TitledPane
protected TitledPane createTitledPaneCoastalConcentratedPipe(int index){

    TilePane tile = new TilePane(Orientation.HORIZONTAL, 5, 5);
    Label typeLabel = new Label("Тип выпуска");
    ChoiceBox<String> choiceBoxTypeOfPipe = createChoiceBoxTypeOfPipes();
    choiceBoxTypeOfPipe.getSelectionModel().select(0);
    choiceBoxTypeOfPipe.setPrefWidth(choiceBoxTypeOfPipe.USE_COMPUTED_SIZE);
    choiceBoxTypeOfPipe.setPrefHeight(choiceBoxTypeOfPipe.USE_COMPUTED_SIZE);
    VBox typeContainer = new VBox(typeLabel,choiceBoxTypeOfPipe);

    Label bankLabel = new Label("Берег");
    bankLabel.setId("textWithTooltip");
    Tooltip.install(bankLabel, new Tooltip("Берег, с которого производится выпуск"));
    ChoiceBox<String> choiceBoxCoast = createChoiceBoxCoast();
    choiceBoxCoast.getSelectionModel().select(0);
    VBox bankContainer = new VBox(bankLabel, choiceBoxCoast);

    Label labelCoordinateX = new Label("Точка выпуска (км)");
    Tooltip.install(labelCoordinateX, new Tooltip("Координата x точки выпуска относительно положения контрольного створа"));
    labelCoordinateX.setId("textWithTooltip");

    TextField textFieldCoordinate = new TextField();

    VBox coordinateContainer = new VBox(labelCoordinateX, textFieldCoordinate);

    tile.getChildren().addAll(typeContainer, bankContainer, coordinateContainer);

    TitledPane titledPane = new TitledPane("Параметры выпуска " + (index+1), tile);

    return titledPane;
}

//Create the second type of a TitledPane
protected TitledPane createTitledPaneCoastalSpreadPipe(int index){

    TilePane tile = new TilePane(Orientation.HORIZONTAL, 5, 5);
    Label typeLabel = new Label("Тип выпуска");
    ChoiceBox<String> choiceBoxTypeOfPipe = createChoiceBoxTypeOfPipes();
    choiceBoxTypeOfPipe.getSelectionModel().select(1);
    VBox typeContainer = new VBox(typeLabel,choiceBoxTypeOfPipe);

    Label bankLabel = new Label("Берег");
    bankLabel.setId("textWithTooltip");
    Tooltip.install(bankLabel, new Tooltip("Берег, с которого производится выпуск"));
    ChoiceBox<String> choiceBoxCoast = createChoiceBoxCoast();
    choiceBoxCoast.getSelectionModel().select(0);
    VBox bankContainer = new VBox(bankLabel, choiceBoxCoast);

    Label labelCoordinateX = new Label("Точка выпуска (км)");
    labelCoordinateX.setId("textWithTooltip");
    Tooltip.install(labelCoordinateX, new Tooltip("Координата x точки выпуска относительно положения контрольного створа"));

    TextField textFieldCoordinate = new TextField();
    VBox coordinateContainer = new VBox(labelCoordinateX, textFieldCoordinate);

    Label labelLength = new Label("Распределенная часть (м)");
    labelLength.setId("textWithTooltip");
    Tooltip.install(labelLength, new Tooltip("Длина распределенной части выпуска (м)"));
    TextField textFieldLength = new TextField();
    VBox lengthContainer = new VBox(labelLength, textFieldLength);

    tile.getChildren().addAll(typeContainer, bankContainer, coordinateContainer, lengthContainer);

    TitledPane titledPane = new TitledPane("Параметры выпуска " + (index+1), tile);


    return titledPane;
}

//creates choiceBox of pipes
protected ChoiceBox<String> createChoiceBoxTypeOfPipes(){
    return new ChoiceBox(FXCollections.observableArrayList("Береговой сосредоточенный",
            "Береговой распределенный", "Русловой сосредоточенный", "Русловой рассеивающий",
            "Русловой рассеивающий с двумя ветками выпуска"));

}

}

I don't save nodes' instances because i have no idea how to change them after recreating. I guess we need to get to know the titled pane, where choice box was changed, after that recreate this titled pane. BUT we need restore the previous data and my methods cant restore them. So, please.

SOLUTION

Thanks to James_D, i found the solution: I just needed ArrayList<Map<String, Node>> each Map contains TextField s and ChoiceBox es.

protected TitledPane createTitledPanePipe(int index){

    Map<String, Node> content = new HashMap<>();

    /* Базовая часть всех труб */
    TilePane tile = new TilePane(Orientation.HORIZONTAL, 5, 5);
    Label typeLabel = new Label("Тип выпуска");
    ChoiceBox<String> choiceBoxTypeOfPipe = createChoiceBoxTypeOfPipes();
    choiceBoxTypeOfPipe.getSelectionModel().select("Береговой сосредоточенный");
    content.put("choiceBoxTypeOfPipe", choiceBoxTypeOfPipe);
    VBox typeContainer = new VBox(typeLabel,choiceBoxTypeOfPipe);



    Label bankLabel = new Label("Берег");
    bankLabel.setId("textWithTooltip");
    Tooltip.install(bankLabel, new Tooltip("Берег, с которого производится выпуск"));
    ChoiceBox<String> choiceBoxCoast = createChoiceBoxCoast();
    content.put("choiceBoxCoast", choiceBoxCoast);
    VBox bankContainer = new VBox(bankLabel, choiceBoxCoast);


    Label labelCoordinateX = new Label("Точка выпуска (км)");
    labelCoordinateX.setId("textWithTooltip");
    Tooltip.install(labelCoordinateX, new Tooltip("Координата x точки выпуска относительно положения контрольного створа"));
    TextField textFieldCoordinate = new TextField();
    content.put("textFieldCoordinate", textFieldCoordinate);
    VBox coordinateContainer = new VBox(labelCoordinateX, textFieldCoordinate);


    tile.getChildren().addAll(typeContainer, bankContainer, coordinateContainer);

    /*_______________________________________________________*/

    /* Береговая распределенная труба */

    Label labelLength = new Label();
    labelLength.setId("textWithTooltip");
    TextField textFieldLength = new TextField();
    VBox lengthContainer = new VBox(labelLength, textFieldLength);

    Label labelMiniPipes = new Label("Патрубки (м)");
    labelMiniPipes.setId("textWithTooltip");
    Tooltip.install(labelMiniPipes, new Tooltip("Расстояние между патрубками (м)"));
    TextField textFieldMiniPipes = new TextField();
    VBox miniPipesContainer = new VBox(labelMiniPipes, textFieldMiniPipes);

    /* ___________________________________________________________ */

choiceBoxTypeOfPipe.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            switch (oldValue) {
                case "Береговой распределенный":
                    content.keySet().remove("textFieldLength");
                    content.keySet().remove("textFieldMiniPipes");
                    tile.getChildren().remove(lengthContainer);
                    tile.getChildren().remove(miniPipesContainer);
                    break;
                case "Русловой сосредоточенный":
                    content.keySet().remove("textFieldLength");
                    tile.getChildren().remove(lengthContainer);
                    break;

            }
            switch (newValue) {
                case "Береговой распределенный":
                    content.put("textFieldLength", textFieldLength);
                    content.put("textFieldMiniPipes", textFieldMiniPipes);
                    labelLength.setText("Распределенная часть (м)");
                    Tooltip.install(labelLength, new Tooltip("Длина распределенной части выпуска (м)"));
                    tile.getChildren().addAll(lengthContainer, miniPipesContainer);
                    break;
                case "Русловой сосредоточенный":
                    labelLength.setText("Протяженность (м)");
                    content.put("textFieldLength", textFieldLength);
                    Tooltip.install(labelLength, new Tooltip("Расстояние от берега до точки выпуска"));
                    tile.getChildren().addAll(lengthContainer);
                    break;
            }
    });


    TitledPane titledPane = new TitledPane("Параметры выпуска " + index, tile);
    this.dynamicComponents.add(content);
    return titledPane;
}

It's not really clear what the actual problem is here, or why you need two distinct methods.

Why not do:

protected TitledPane createTitledPaneCoastalPipe(int index, boolean concentrate){

    TilePane tile = new TilePane(Orientation.HORIZONTAL, 5, 5);
    Label typeLabel = new Label("Тип выпуска");
    ChoiceBox<String> choiceBoxTypeOfPipe = createChoiceBoxTypeOfPipes();

    // remove this line:
    // choiceBoxTypeOfPipe.getSelectionModel().select(1);

    VBox typeContainer = new VBox(typeLabel,choiceBoxTypeOfPipe);

    Label bankLabel = new Label("Берег");
    bankLabel.setId("textWithTooltip");
    Tooltip.install(bankLabel, new Tooltip("Берег, с которого производится выпуск"));
    ChoiceBox<String> choiceBoxCoast = createChoiceBoxCoast();
    choiceBoxCoast.getSelectionModel().select(0);
    VBox bankContainer = new VBox(bankLabel, choiceBoxCoast);

    Label labelCoordinateX = new Label("Точка выпуска (км)");
    labelCoordinateX.setId("textWithTooltip");
    Tooltip.install(labelCoordinateX, new Tooltip("Координата x точки выпуска относительно положения контрольного створа"));

    TextField textFieldCoordinate = new TextField();
    VBox coordinateContainer = new VBox(labelCoordinateX, textFieldCoordinate);

    Label labelLength = new Label("Распределенная часть (м)");
    labelLength.setId("textWithTooltip");
    Tooltip.install(labelLength, new Tooltip("Длина распределенной части выпуска (м)"));
    TextField textFieldLength = new TextField();
    VBox lengthContainer = new VBox(labelLength, textFieldLength);

    tile.getChildren().addAll(typeContainer, bankContainer, coordinateContainer);

    choiceBoxTypeOfPipes.getSelectionModel().selectedIndexProperty().addListener(
        (obs, oldIndex, newIndex) -> {
            // may need different logic here: question is unclear
            if (newIndex.intValue()==1) {
                tile.getChildren().add(lengthContainer);
            }
            if (oldIndex.intValue()==1) {
                tile.getChildren().remove(lengthContainer);
            }
        }
    );

    if (concentrate) {
        choiceBoxTypeOfPipes.getSelectionModel().select(0);
    } else {
        choiceBoxTypeOfPipes.getSelectionModel().select(1);
    }

    TitledPane titledPane = new TitledPane("Параметры выпуска " + (index+1), tile);


    return titledPane;
}

and then just

public void fillAccordion(int numberOfPipes){

    accordionPlant.getPanes().add(createTitledPaneCoastalPipe(0, true));
    accordionPlant.getPanes().add(createTitledPaneCoastalPipe(1, false));

}

Doesn't that do what you want, without all the redundant code?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM