简体   繁体   English

Javafx:使用 FXML 的可重用集合

[英]Javafx: Reusable collections using FXML

I'd like to bind a single collection to multiple ChoiceBox's in FXML.我想将单个集合绑定到 FXML 中的多个 ChoiceBox。 However the only way I know how is using:但是,我知道如何使用的唯一方法是:

<ChoiceBox fx:id="cb00" prefWidth="150.0" GridPane.rowIndex="0" GridPane.columnIndex="0">
    <items>
        <FXCollections fx:id="test" fx:factory="observableArrayList">
            <String fx:value="1" />
            <String fx:value="2" />
            <String fx:value="3" />
            <String fx:value="4" />
            <String fx:value="5" />
            <String fx:value="6" />
            <String fx:value="7" />
            <String fx:value="8" />
            <String fx:value="9" />
        </FXCollections>
    </items>
</ChoiceBox>

Is it possible to declare the collection in the controller and refer to it in FXML instead of copying the collection for each ChoiceBox?是否可以在控制器中声明集合并在 FXML 中引用它而不是为每个 ChoiceBox 复制集合?

You can define the items in the controller:您可以在控制器中定义项目:

public class Controller {

    private ListProperty<String> choiceBoxItems = new SimpleListProperty(FXCollections.observableArrayList());

    public Controller() {
        IntStream.range(1,10).mapToObj(i -> Integer.toString(i))
            .forEach(choiceBoxItems::add);
    }

    public ListProperty<String> choiceBoxItemsProperty() {
        return choiceBoxItems ;
    }

    public ObservableList<String> getChoiceBoxItems() {
        return choiceBoxItemsProperty().get() ;
    }

    public void setComboBoxItems(ObservableList<String> choiceBoxItems) {
        choiceBoxItemsProperty().set(choiceBoxItems) ;
    }

    // ...
}

and then (this is not tested, but I think it will work):然后(这没有经过测试,但我认为它会起作用):

<ChoiceBox fx:id="cb00" items="${controller.choiceBoxItems}" prefWidth="150.0" GridPane.rowIndex="0" GridPane.columnIndex="0">

See expression binding in the FXML documentation.请参阅 FXML 文档中的表达式绑定 (It's not actually documented that the controller is available in the FXML namespace with key controller , but I think it is safe to use this.) (实际上并没有证明控制器在 FXML 命名空间中可用,键为controller ,但我认为使用它是安全的。)

You can also just define the list in the FXML using fx:define :您也可以使用fx:define在 FXML 中定义列表:

<fx:define>

    <FXCollections fx:id="choiceBoxItems" fx:factory="observableArrayList">
        <String fx:value="1"/>
        <String fx:value="2"/>
        <String fx:value="3"/>
        <!-- ... -->
    </FXCollections>

</fx:define>

and then refer to it in each choice box:然后在每个选择框中引用它:

<ChoiceBox fx:id="cb00" items="${choiceBoxItems}" prefWidth="150.0" GridPane.rowIndex="0" GridPane.columnIndex="0">

It can be in the controller or any other class like (the example is for a combobox. The same can be applied to a choicebox):它可以在控制器或任何其他类中(该示例适用于组合框。同样可以应用于选择框):

combo.fxml组合文件

<?import javafx.scene.control.ComboBox?>
<ComboBox  fx:id="combo1" items="${itemLoader.items}"  prefWidth="150.0"  
xmlns:fx="http://javafx.com/fxml/1" >
</ComboBox>

Loader class加载器类

public class ComboLoader {

    private ObservableList<String> obsStrings;

    public ComboLoader() {

        obsStrings = FXCollections.observableArrayList(createStrings());
    }

    private List<String> createStrings() {
            return IntStream.rangeClosed(0, 5)
                    .mapToObj(i -> "String "+i)
                    .map(String::new)
                    .collect(Collectors.toList());
    }
    //name of this method corresponds to itemLoader.items in xml.
    //if xml name was itemLoader.a this method should have been
    //getA(). A bit odd
    public ObservableList<String> getItems(){

        return obsStrings;
    }
}

test it with:测试它:

public class ComboTest extends Application {

    @Override
    public void start(Stage primaryStage) throws IOException {

        primaryStage.setTitle("Populate combo from custom builder");

        Group group = new Group();
        GridPane grid = new GridPane();
        grid.setPadding(new Insets(25, 25, 25, 25));
        group.getChildren().add(grid);

        FXMLLoader loader = new FXMLLoader(getClass().getResource("combo.fxml"));
        loader.getNamespace().put("itemLoader", new ComboLoader());
        ComboBox<String>combo = loader.load();
        grid.add(combo, 0, 0);

        Scene scene = new Scene(group, 450, 175);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

在此处输入图片说明

You can use <fx:reference> to reference existing objects by their fx:id .您可以使用<fx:reference>通过fx:id引用现有对象。 Using this tag you can reuse the ObservableList :使用这个标签你可以重用ObservableList

<HBox xmlns:fx="http://javafx.com/fxml/1" spacing="10">
    <children>
        <ChoiceBox prefWidth="150.0">
            <items>
                <FXCollections fx:id="test" fx:factory="observableArrayList">
                    <String fx:value="1" />
                    <String fx:value="2" />
                    <String fx:value="3" />
                    <String fx:value="4" />
                    <String fx:value="5" />
                    <String fx:value="6" />
                    <String fx:value="7" />
                    <String fx:value="8" />
                    <String fx:value="9" />
                </FXCollections>
            </items>
        </ChoiceBox>
        <ChoiceBox prefWidth="150.0">
            <items>
                <fx:reference source="test" /> <!-- reuse other list here -->
            </items>
        </ChoiceBox>
    </children>
</HBox>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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