【问题标题】:Initializing TableView with columns inside fx:root using FXML使用 FXML 使用 fx:root 中的列初始化 TableView
【发布时间】:2022-01-19 15:03:00
【问题描述】:

我在名为TablePatientView 的 fxml 文件中有一个自定义类。我像<TablePatientView fx:id="tablePatientView" layoutX="20.0" layoutY="45.0" prefHeight="409.0" prefWidth="363.0" /> 一样使用它,它几乎可以正常工作。 fx:root 如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>

<fx:root type="javafx.scene.control.TableView" xmlns:fx="http://javafx.com/fxml">
    <TableView>
        <columns>
            <TableColumn fx:id="patId" prefWidth="101.0" text="Patient-ID" />
            <TableColumn fx:id="patVorname" prefWidth="69.0" text="Vorname" />
            <TableColumn fx:id="patNachname" prefWidth="98.0" text="Nachname" />
            <TableColumn fx:id="patGebdat" prefWidth="96.0" text="Geburtsdatum" />
        </columns>
    </TableView>
</fx:root>

下面的类

public class TablePatientView extends TableView<TablePatient> {

    private Parent root;

    @FXML
    private TableColumn<TablePatient,String> patId;
    @FXML
    private TableColumn<TablePatient,String> patVorname;
    @FXML
    private TableColumn<TablePatient,String> patNachname;
    @FXML
    private TableColumn<TablePatient, LocalDate> patGebdat;

    public TablePatientView() {
        FXMLLoader loader = new FXMLLoader(Main.class.getResource("/fxml/TablePatientView.fxml"));
        loader.setController(this);
        loader.setRoot(this);
        try {
            root = loader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
        setCellValueFactories();
        // getColumns().addAll(patId, patVorname, patNachname, patGebdat); works, but not with plain fxml
    }

    private void setCellValueFactories() {
        patId.setCellValueFactory(param -> param.getValue().idProperty().asString());
        patVorname.setCellValueFactory(param -> param.getValue().vornameProperty());
        patNachname.setCellValueFactory(param -> param.getValue().nachnameProperty());
        patGebdat.setCellValueFactory(param -> param.getValue().gebDatProperty());
    }
}

列已正确初始化,但由于某种原因未作为列添加到 TableView。 我知道我可以通过 java 代码来做到这一点(参见上面代码中的注释行),但我想知道为什么这不适用于 fxml。直接在 fxml 中使用 没有自定义类和根就可以了。

【问题讨论】:

    标签: java javafx


    【解决方案1】:

    &lt;fx:root type="TableView"&gt; 引用了通过调用 loader.setRoot(this) 提供的 TableView

    您在 TableView1 中定义了另一个 TableView。这些列被添加到TableView,而不是&lt;fx:root&gt; 引用的列。

    正确的 FXML 是

    <?xml version="1.0" encoding="UTF-8"?>
    <?import javafx.scene.control.*?>
    
    <fx:root type="javafx.scene.control.TableView" xmlns:fx="http://javafx.com/fxml">
        <columns>
            <TableColumn fx:id="patId" prefWidth="101.0" text="Patient-ID" />
            <TableColumn fx:id="patVorname" prefWidth="69.0" text="Vorname" />
            <TableColumn fx:id="patNachname" prefWidth="98.0" text="Nachname" />
            <TableColumn fx:id="patGebdat" prefWidth="96.0" text="Geburtsdatum" />
        </columns>
    </fx:root> 
    

    替代方法

    我不太喜欢继承控制类,例如TableView。原因是您并没有真正为TableView 添加功能,您只是在本质上在其上设置属性,这不是对继承的良好使用。

    考虑改为使用创建模式。一个简单的静态工厂方法运行良好,并且通过 fx:factory 属性与 FXML 很好地配合。

    TablePatientView.fxml:

    <?xml version="1.0" encoding="UTF-8"?>
    <?import javafx.scene.control.*?>
    
    <TableView xmlns:fx="http://javafx.com/fxml" fx:controller="com.jamesd.examples.TablePatientController">
        <columns>
            <TableColumn fx:id="patId" prefWidth="101.0" text="Patient-ID" />
            <TableColumn fx:id="patVorname" prefWidth="69.0" text="Vorname" />
            <TableColumn fx:id="patNachname" prefWidth="98.0" text="Nachname" />
            <TableColumn fx:id="patGebdat" prefWidth="96.0" text="Geburtsdatum" />
        </columns>
    </TableView>
    

    TablePatientController.java:

    public class TablePatientController {
    
        @FXML
        private TableColumn<TablePatient,String> patId;
        @FXML
        private TableColumn<TablePatient,String> patVorname;
        @FXML
        private TableColumn<TablePatient,String> patNachname;
        @FXML
        private TableColumn<TablePatient, LocalDate> patGebdat;
        
        @FXML
        private void initialize() {
            setCellValueFactories();
        }
    
        private void setCellValueFactories() {
            patId.setCellValueFactory(param -> param.getValue().idProperty().asString());
            patVorname.setCellValueFactory(param -> param.getValue().vornameProperty());
            patNachname.setCellValueFactory(param -> param.getValue().nachnameProperty());
            patGebdat.setCellValueFactory(param -> param.getValue().gebDatProperty());
        }
    }
    

    Tables.java:

    public class Tables {
    
        public static TableView<TablePatient> tablePatientView() throws Exception {
            FXMLLoader loader = new FXMLLoader(Main.class.getResource("/fxml/TablePatientView.fxml"));
            return loader.load();
        }
    }
    

    然后你可以在 FXML 中使用它

    <Tables fx:factory="tablePatientView" />
    

    脚注

    1. 这里发生的情况是第二个TableView 被添加到原始TableViewitems 列表中,因为TableView@DefaultProperty 就是那个列表。所以最终表格视图会尝试将其显示为表格中的一行。似乎在某个时候应该有一个ClassCastException,但由于 FXML 无法指定泛型类型,它可能会被静默压扁。

    【讨论】:

    • 非常感谢,您解决了我的问题。首先你是对的,我后来确实收到了ClassCastException。我扩展了TableView,因为我想整理我的另一个控制器,其中包含3个单独的TableViews和一些按钮。我会试试静态工厂,再次感谢:)
    • @wand555 也可以考虑使用fx:include
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    • 2021-08-08
    • 2015-05-05
    • 2018-07-15
    • 2020-05-14
    相关资源
    最近更新 更多