【问题标题】:Bind TableView items with ObservableList in FXML - Java FX在 FXML 中将 TableView 项与 ObservableList 绑定 - Java FX
【发布时间】:2017-01-15 16:43:51
【问题描述】:

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

当我在按钮单击事件中设置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;
    }
}

【问题讨论】:

    标签: java javafx fxml


    【解决方案1】:

    如果您从MainSceneController 的构造函数中调用getMaterialsFromRESTController()(因此一旦控制器对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);
        }
    }
    

    【讨论】:

    • 谢谢,对我帮助很大!
    • 感谢您的帮助。我将initialize() 方法添加到TableController 以在不单击按钮的情况下加载项目。如果对某人有帮助,可以使用代码here
    猜你喜欢
    • 2018-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多