Какой хороший способ получить fx: id из текстового поля из fxml, содержащего не менее 40 текстовых полей - PullRequest
0 голосов
/ 28 августа 2018

Я столкнулся с проблемой, когда у меня есть приложение, которому нужно около 40 уникальных текстовых полей (вместе с соответствующей меткой).

Однако проблема, с которой я сталкиваюсь, заключается в том, что я не могу придумать, как правильно это настроить и получить их поля fx: id в контроллере.

Если я создаю все текстовые поля и метку в HBox в FXML, то у меня нет способа получить весь fx: id из контроллера, и в настоящее время я просто копирую и вставляю идентификатор из FXML в контроллер, а затем установить код для сопоставления текстового поля с их идентификатором. Это звучит глупо, так как никогда не будет масштабироваться, а также означает, что если я изменю fx: id на FXML, то я должен также изменить его в контроллере.

Есть ли лучший способ сделать это?

1 Ответ

0 голосов
/ 28 августа 2018

Хотя ваш вопрос не дает четкого представления о конечной цели, некоторые другие пользователи предложили использовать цикл в вашем коде Java для создания TextFields.

Я согласен, так как то, что вы описываете, вероятно, не лучше всего подходит для FXML, так как это гораздо проще сделать с помощью кода Java.

В приведенном ниже примере используется объект пользовательской модели данных с именем TextInput, который содержит как TextField, так и связанный с ним Label.

Сам код также прокомментирован с дополнительным пониманием.

КОД

Main.java - Просто используется для запуска приложения и отображения сцены:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class Main extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Layout.fxml"));
            loader.setController(new Controller());

            primaryStage.setScene(new Scene(loader.load()));
            primaryStage.setTitle("Dynamic TextFields Example");
            primaryStage.show();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

Layout.fxml - простой макет графического интерфейса, содержащий GridPane, используемый для отображения данных TextInput:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.*?>
<VBox alignment="TOP_CENTER" prefHeight="400.0" prefWidth="300.0" spacing="10.0" xmlns="http://javafx.com/javafx/9.0.1"
      xmlns:fx="http://javafx.com/fxml/1">
    <children>
        <ScrollPane fitToHeight="true" fitToWidth="true" VBox.vgrow="ALWAYS">
            <content>
                <GridPane fx:id="gridPane" hgap="10.0" vgap="5.0">
                    <columnConstraints>
                        <ColumnConstraints hgrow="NEVER" minWidth="-Infinity"/>
                        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
                    </columnConstraints>
                    <rowConstraints>
                        <RowConstraints minHeight="-Infinity" prefHeight="30.0" vgrow="NEVER"/>
                    </rowConstraints>
                </GridPane>
            </content>
            <padding>
                <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
            </padding>
        </ScrollPane>
        <Button fx:id="btnGetInputText" mnemonicParsing="false" text="Get Input 4 Text"/>
    </children>
    <padding>
        <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
    </padding>
</VBox>

Controller.java - контроллер для макета FXML

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;

import java.util.ArrayList;
import java.util.List;

public class Controller {

    @FXML
    private GridPane gridPane;
    @FXML
    private Button btnGetInputText;

    // List of new TextInput objects
    List<TextInput> textInputs = new ArrayList<>();

    @FXML
    private void initialize() {

        // Here we will generate 40 new TextInput objects.
        for (int i = 0; i < 40; i++) {
            TextInput input = new TextInput(
                    "Input " + i,
                    new Label("Input " + i + ":"),
                    new TextField()
            );

            // Now, add the new TextInput Label and TextField to the GridPane
            gridPane.add(input.getLabel(), 0, i);
            gridPane.add(input.getTextField(), 1, i);

            // Finally, add the input to the list so they can be retrieved later using the input's Name
            textInputs.add(input);
        }

        // Use the button to print out the text from Input #4
        btnGetInputText.setOnAction(e -> {
            System.out.println("Input #4: " + getInputTextByName("Input 4"));
        });
    }

    /**
     * Helper method to get the value of a specific TextField
     */
    private String getInputTextByName(String name) {

        // Loop through the list of TextInput objects and get the one with the desired name
        for (TextInput input :
                textInputs) {
            if (input.getName().equalsIgnoreCase(name)) {
                return input.getTextField().getText();
            }
        }

        // If not found, return null (or empty String, if desired)
        return null;

    }
}

/**
 * Custom data structure to hold both the Label and TextFields for your inputs. There is also a Name field that can
 * be any type you wish, but provides a way of locating the right TextField when you need to. This could just as
 * easily be done with an ID or searching label.getText(), but I'm using a separate field in this sample for simplicity.
 */
class TextInput {

    private final String name;
    private final Label label;
    private final TextField textField;

    public TextInput(String name, Label label, TextField textField) {
        this.name = name;
        this.label = label;
        this.textField = textField;
    }

    public String getName() {
        return name;
    }

    public Label getLabel() {
        return label;
    }

    public TextField getTextField() {
        return textField;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...