简体   繁体   English

使用 FXML 使用 fx:root 中的列初始化 TableView

[英]Initializing TableView with columns inside fx:root using FXML

I have a custom class inside a fxml file called TablePatientView .我在名为TablePatientView I use it like <TablePatientView fx:id="tablePatientView" layoutX="20.0" layoutY="45.0" prefHeight="409.0" prefWidth="363.0" /> and it works almost fine.我像<TablePatientView fx:id="tablePatientView" layoutX="20.0" layoutY="45.0" prefHeight="409.0" prefWidth="363.0" />一样使用它,它几乎可以正常工作。 The fx:root looks like the following: 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>

with the following class与以下 class

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

The columns are correctly initialized, but for some reason not added as columns to the TableView.列已正确初始化,但由于某种原因未作为列添加到 TableView。 I know I can do it via java code (see the commented line in the code above) but I would like to know why this doesn't work with just fxml.我知道我可以通过 java 代码来做到这一点(参见上面代码中的注释行),但我想知道为什么这不适用于 fxml。 Using the <TableView> directly inside fxml without a custom class and root works just fine.在没有自定义 class 和 root 的情况下直接在 fxml 中使用 <TableView> 就可以了。

The <fx:root type="TableView"> references a TableView which is supplied via the call to loader.setRoot(this) . <fx:root type="TableView">引用通过调用loader.setRoot(this)提供的TableView

You have defined another TableView inside that TableView 1 .您已经在该TableView 1中定义了另一个TableView The columns are added to that TableView , not the one referenced by <fx:root> .这些列被添加到该TableView ,而不是<fx:root>引用的列。

The correct FXML is正确的 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> 

Alternative approach替代方法

I'm not a big fan of subclassing control classes, such as TableView .我不喜欢继承控件类,例如TableView The reason is that you're not really adding functionality to the TableView , you're just essentially setting properties on it, and this is not a good use of inheritance.原因是您并没有真正向TableView添加功能,您只是在本质上设置属性,这不是 inheritance 的好用处。

Consider instead using a creational pattern.考虑改为使用创建模式。 A simple static factory method works well, and plays nicely with FXML via the fx:factory attribute.一个简单的 static 工厂方法运行良好,并通过fx:factory属性与 FXML 很好地配合使用。

TablePatientView.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: TablePatientController.java:

public class TablePatientContorller {

    @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:表.java:

public class Tables {

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

And then you can use this in FXML with然后你可以在 FXML 中使用它

<Tables fx:factory="tablePatientView" />

Footnote脚注

  1. What happens here is that the second TableView is added to the original TableView 's items list, since the @DefaultProperty of a TableView is that list.这里发生的是第二个TableView被添加到原始TableViewitems列表中,因为TableView@DefaultProperty就是那个列表。 So eventually the table view would attempt to display that as a row in the table.所以最终表格视图会尝试将其显示为表格中的一行。 It seems like there should be a ClassCastException at some point, but possibly it gets silently squashed since FXML can't specify generic types.似乎在某些时候应该有一个ClassCastException ,但由于 FXML 无法指定泛型类型,它可能会被静默地压扁。

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

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