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

时间:2017-01-15 16:43:52

标签: java javafx fxml

我无法将TableView项与ObservableList绑定在FXML中。

在按钮点击事件中设置materialTable.setItems(materialDataObservableList);时,一切正常。 但我不想让按钮知道TableView,所以我想将materialTable.items绑定到materialDataObservableList属性。

我做错了什么? 或者也许我不明白具有约束力的作用......

感谢您的帮助!

<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;
    }
}

1 个答案:

答案 0 :(得分:3)

如果您从getMaterialsFromRESTController()的构造函数调用MainSceneController(因此只要控制器可用于FXMLLoader就会初始化),那么

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

会奏效。 (请注意,您使用${controller.property}访问控制器的属性。)

如果没有,您可以按如下方式修改控制器以使其工作:

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;
    }

}

然后上面的FXML应该可以工作。

这是一个SSCCE:

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:

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(应用程序类):

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);
    }
}