简体   繁体   English

在FXML中使用ObservableList绑定TableView项 - Java FX

[英]Bind TableView items with ObservableList in FXML - Java FX

I'm unable to bind TableView items with ObservableList in FXML. 我无法在FXML中将TableView项与ObservableList绑定。

Everything works fine when I set materialTable.setItems(materialDataObservableList); 当我设置materialTable.setItems(materialDataObservableList);时,一切正常materialTable.setItems(materialDataObservableList); in button click event. 在按钮单击事件中。 But I don't want button to know about TableView so I wanted to bind materialTable.items to materialDataObservableList property. 但我不希望按钮知道TableView所以我想将materialTable.items绑定到materialDataObservableList属性。

What am I doing wrong? 我究竟做错了什么? Or maybe I don't understand how binding works... 或许我不明白具有约束力的作用......

Thanks for help! 感谢帮助!

<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="464.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.xxx.sm.frontend.fx.MainSceneController">
/*
*/
<children>
    <VBox prefHeight="200.0" prefWidth="100.0">
        <children>
            <Button fx:id="getMaterialsButton" mnemonicParsing="false" onAction="#getMaterialsButton" text="Get materials" />
            <TableView fx:id="materialTable" editable="true" prefHeight="413.0" prefWidth="600.0" items="${materialDataObservableList}" >
                //Columns here
              <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
           </columnResizePolicy>
            </TableView>
        </children>
    </VBox>
</children>

public class MainSceneController {

    private ObservableList<MaterialData> materialDataObservableList;
    public TableView materialTable;
    public Button getMaterialsButton;

    public void getMaterialsButton() {
        getMaterialsFromRESTController();
    }

    private void getMaterialsFromRESTController() {
        MaterialClient controller = new MaterialClient();
        try {
            materialDataObservableList = FXCollections.observableArrayList(controller.getMaterias());
        } catch (IOException e) {
            System.out.println("Failed to connect to RESTController");
        }
        //materialTable.setItems(materialDataObservableList);
    }

    public ObservableList<MaterialData> getMaterialDataObservableList() {
        return materialDataObservableList;
    }
}

If you are calling getMaterialsFromRESTController() from MainSceneController 's constructor (so it is initialized as soon as the controller is available to the FXMLLoader ), then 如果从MainSceneController的构造函数中调用getMaterialsFromRESTController() (因此只要控制器可用于FXMLLoader就会初始化),那么

<TableView fx:id="materialTable" editable="true" prefHeight="413.0" prefWidth="600.0" 
    items="${controller.materialDataObservableList}" >

will work. 将工作。 (Note you access a property of the controller with ${controller.property} .) (注意,您使用${controller.property}访问控制器的属性。)

If not, you can modify the controller as follows to make it work: 如果没有,您可以按如下方式修改控制器以使其工作:

public class MainSceneController {


    private final ObservableList<MaterialData> materialDataObservableList 
        = FXCollections.observableArrayList();
    public TableView materialTable;
    public Button getMaterialsButton;

    public void getMaterialsButton() {
        getMaterialsFromRESTController();
    }

    private void getMaterialsFromRESTController() {
        MaterialClient controller = new MaterialClient();
        try {
            materialDataObservableList.setAll(controller.getMaterias());
        } catch (IOException e) {
            System.out.println("Failed to connect to RESTController");
        }
    }

    public ObservableList<MaterialData> getMaterialDataObservableList() {
        return materialDataObservableList;
    }

}

and then the above FXML should work. 然后上面的FXML应该工作。


Here is a SSCCE: 这是一个SSCCE:

BindTableItemsExample.fxml: BindTableItemsExample.fxml:

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

<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.control.Button?>
<?import javafx.geometry.Insets?>

<BorderPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="TableController">
    <center>
        <TableView items="${controller.items}">
            <columns>
                <TableColumn text="Item">
                    <cellValueFactory><PropertyValueFactory property="name" /></cellValueFactory>
                </TableColumn>
            </columns>
        </TableView>
    </center>
    <bottom>
        <Button text="Load" onAction="#loadItems" BorderPane.alignment="center" >
            <BorderPane.margin>
                <Insets top="5" left="5" right="5" bottom="5"/>
            </BorderPane.margin>
        </Button>
    </bottom>
</BorderPane>

TableController.java: TableController.java:

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;

public class TableController {

    private final ObservableList<Item> items = FXCollections.observableArrayList();

    @FXML
    private void loadItems() {
        items.setAll(createItems());
    }

    private List<Item> createItems() {
        return IntStream.rangeClosed(1, 100)
                .mapToObj(i -> "Item "+i)
                .map(Item::new)
                .collect(Collectors.toList());
    }

    public ObservableList<Item> getItems() {
        return items ;
    }


    public static class Item {
        private final StringProperty name = new SimpleStringProperty();

        public Item(String name) {
            setName(name);
        }

        public final StringProperty nameProperty() {
            return this.name;
        }

        public final java.lang.String getName() {
            return this.nameProperty().get();
        }

        public final void setName(final java.lang.String name) {
            this.nameProperty().set(name);
        }

    }
}

BindTableItemsTest.java (application class): BindTableItemsTest.java(应用程序类):

import java.io.IOException;

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

public class BindTableItemsTest extends Application {

    @Override
    public void start(Stage primaryStage) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("BindTableItemsExample.fxml"));
        primaryStage.setScene(new Scene(loader.load(), 600, 600));
        primaryStage.show();
    }

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

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

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