TableView <t>不显示ObservableList <t>对象的内容</t> </t>

时间:2014-07-23 14:34:46

标签: java javafx javafx-8

我有两个几乎相似的用于存储简单字符串数据的自定义类 - 它们被称为“患者”和“跟踪”。它们彼此之间的区别仅在于已定义字段的数量。两者的构造函数如下所示(使用getVariablesNames()静态方法):

public class Patient {

    String patientID;
    String firstName;
    String lastName;
    String gender;
    String dateOfBirth;
    String age;
    String email;
    String phoneNumber;
    String city;

    public Patient(String patientID, String firstName, String lastName, String gender, String dateOfBirth, String age, String email, String phoneNumber, String city) {
        this.patientID = patientID;
        this.firstName = firstName;
        this.lastName = lastName;
        this.gender = gender;
        this.dateOfBirth = dateOfBirth;
        this.age = age;
        this.email = email;
        this.phoneNumber = phoneNumber;
        this.city = city;
    }

    public static String[] getVariablesNames() {
        Field[] fields = Patient.class.getDeclaredFields();
        String[] variablesNames = new String[fields.length];
        for (int i = 0; i < fields.length; i++) {
            variablesNames[i] = fields[i].getName();
        }
        return variablesNames;
    }

    public String getPatientID() {
        return patientID;
    }

    public void setPatientID(String value) {
        patientID = value;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String value) {
        firstName = value;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String value) {
        lastName = value;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String value) {
        gender = value;
    }

    public String getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(String value) {
        dateOfBirth = value;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String value) {
        age = value;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String value) {
        email = value;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String value) {
        phoneNumber = value;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String value) {
        city = value;
    }
}

“Trace”类的构造函数:

public class Trace {

    String action;
    String status;
    String message;
    String time;

    public Trace(String action, String status, String message, String time) {
        this.action = action;
        this.status = status;
        this.message = message;
        this.time = time;
    }

    public static String[] getVariablesNames() {
        Field[] fields = Trace.class.getDeclaredFields();
        String[] variablesNames = new String[fields.length];
        for (int i = 0; i < fields.length; i++) {
            variablesNames[i] = fields[i].getName();
        }
        return variablesNames;
    }

    public void setActionText(String value) {
        action = value;
    }

    public String getActionText() {
        return action;
    }

    public void setStatusText(String value) {
        status = value;
    }

    public String getStatusText() {
        return status;
    }

    public void setMessageText(String value) {
        message = value;
    }

    public String getMessageText() {
        return message;
    }

    public void setTimeText(String value) {
        time = value;
    }

    public String getTimeText() {
        return time;
    }
}

我使用这些类的对象来填充自定义TableView<T>个实例,其中<T>可以是“患者”或“跟踪”。我遇到的问题是“Trace”对象值没有显示在表中,其中“Patient”类的对象没有问题。自定义TableView<T>类如下所示:

import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;

public class TableViewCustom<T> extends TableView<T> {

    public TableViewCustom(String[] columnNames, String[] variablesNames, ObservableList<T> data) {
        super();

        @SuppressWarnings("unchecked")
        TableColumn<T, String>[] tableColumns = new TableColumn[variablesNames.length];
        for (int i = 0; i < tableColumns.length; i++) {
            tableColumns[i] = new TableColumn<T, String>(columnNames[i]);
            tableColumns[i].setCellValueFactory(new PropertyValueFactory<T, String>(variablesNames[i]));
        }

        this.setItems(data);
        this.getColumns().addAll(tableColumns);

        this.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    }
}

使用“Patient”和“Trace”对象的自定义TableView的示例实现:

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Demo extends Application {

    public Parent createContent() {

        /* layout */
        BorderPane layout = new BorderPane();

        /* layout -> center */
        VBox tableViewsContainer = new VBox(5);

        /* layout -> center -> top */
        String[] patientColumnNames = new String[] {"Patient ID", "First Name", "Last Name", "Gender", "Date Of Birth", "Age", "Email", "Phone Number", "City"};
        String[] patientVariablesNames = Patient.getVariablesNames();
        ObservableList<Patient> patientData = FXCollections.observableArrayList(new Patient("Patient ID", "First Name", "Last Name", "Gender", "Date Of Birth", "Age", "Email", "Phone Number", "City"));
        TableViewCustom<Patient> patientTableView = new TableViewCustom<Patient>(patientColumnNames, patientVariablesNames, patientData);

        /* layout -> center -> bottom */
        String[] traceColumnNames = new String[] {"Action", "Status", "Message", "Time"};
        String[] traceVariablesNames = Trace.getVariablesNames();
        ObservableList<Trace> traceData = FXCollections.observableArrayList(new Trace("Action", "Status", "Message", "Time"));
        TableViewCustom<Trace> traceTableView = new TableViewCustom<Trace>(traceColumnNames, traceVariablesNames, traceData);

        /* add items to the layout */
        tableViewsContainer.getChildren().addAll(patientTableView, traceTableView);

        layout.setCenter(tableViewsContainer);
        return layout;
    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(createContent()));
        stage.setWidth(700);
        stage.setHeight(400);
        stage.show();
    }

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

Demo.java应用程序的结果如下所示:

enter image description here

PS我没有收到任何错误。

1 个答案:

答案 0 :(得分:3)

问题是您传递给PropertyValueFactory的值与属性的名称不匹配,这些属性由get...()set...(...)方法定义。

由于您使用反射来查找已定义的字段(而非属性)的名称,因此对于Trace类,传递给PropertyValueFactory的值为“动作”,“状态”,“消息”和“时间”。因此,表视图将尝试通过在每行getAction()个对象上调用getStatus()getMessage()getTime()Trace来填充列的值。由于没有这样的方法,因此您不会显示任何值。

要解决此问题,您可以执行以下操作之一:

  1. getVariablesNames()方法中定义的值进行硬编码以返回属性的名称(即return new String[] {"actionText", "statusText", "messageText", "timeText"};)。由于您在每个类中重复该方法而不是重复使用它,因此您不会使事情变得更加冗长,并且这可能会表现得更好(尽管您不太可能在实践中发现任何差异)。
  2. 使用反射,但查找声明方法的名称,找到所有以“get”或“is”开头的内容,剥去该前缀,并小写剩下的第一个字符。
  3. 使字段名称与属性名称匹配(即将字段声明为actionText等)。这当然会对您的类定义强加约定要求。