TableView与不同的对象(javafx)

Sim*_*agh 2 javafx object tableview

我正在开发一个应用程序,用于观察谁负责不同的患者,但是我还没有能够解决如何用不同的对象类型填充表.

下面是我的TableView控制器的代码.TableView最终会有四种不同的对象类型,所有这些都将从数据库中检索出来.

我希望我的表能够保存Patient对象,User对象(负责人)和RelationManager对象.

以下是我的代码,如果您需要更多代码,请告诉我:-).

package fird.presentation;


import fird.Patient;
import fird.RelationManager;
import fird.User;
import fird.data.DAOFactory;
import fird.data.DataDAO;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;

/**
 * FXML Controller class
 *
 * @author SimonKragh
 */
public class KMAMainFrameOverviewController implements Initializable {

    @FXML
    private TextField txtCPRKMAMainFrame;
    @FXML
    private TableColumn<Patient, String> TableColumnCPR;
    @FXML
    private TableColumn<Patient, String> TableColumnFirstname;
    @FXML
    private TableColumn<Patient, String> TableColumnSurname;
    @FXML
    private TableColumn<User, String> TableColumnResponsible;
    @FXML
    private TableColumn<RelationManager, String> TableColumnLastEdited;
    @FXML
    private TableView<RelationManager> tblPatients;
    @FXML
    private Button btnShowHistory;
    @FXML
    private TableColumn<?, ?> TableColumnDepartment;

    /**
     * Initializes the controller clas @FXML private Button btnShowHistory;
     *
     * @FXML private TableColumn<?, ?> TableColumnDepartment; s.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {

        // Start of logic for the KMAMainFrameOverviewController
        DataDAO dao = DAOFactory.getDataDao();
        TableColumnCPR.setCellValueFactory(new PropertyValueFactory<Patient, String>("CPR"));
        TableColumnFirstname.setCellValueFactory(new PropertyValueFactory<Patient, String>("Firstname"));
        TableColumnSurname.setCellValueFactory(new PropertyValueFactory<Patient, String>("Surname"));
        TableColumnResponsible.setCellValueFactory(new PropertyValueFactory<User, String>("Responsible"));
        TableColumnLastEdited.setCellValueFactory(new PropertyValueFactory<RelationManager, String>("Last Edited"));
        ObservableList<RelationManager> relationData = FXCollections.observableArrayList(dao.getAllActiveRelations());
        tblPatients.setItems(relationData);
        tblPatients.getColumns().addAll(TableColumnCPR, TableColumnFirstname, TableColumnSurname, TableColumnResponsible, TableColumnLastEdited);
        System.out.println(tblPatients.getItems().toString());
    }
}
Run Code Online (Sandbox Code Playgroud)

relationData是返回的RelationManager对象.此对象包含User对象,Patient对象和Responsible对象.

最好,西蒙.

Jam*_*s_D 9

有关如何执行此操作的具体细节取决于您的要求:例如,对于给定的RelationManager对象,与其关联的User,Patient或Responsible对象是否会发生变化?你需要表格可编辑吗?

但基本思路是表中的每一行代表一些RelationManager,因此表类型是TableView<RelationManager>.每列显示某种类型的值(调用它S),因此每列都是类型TableColumn<RelationManager, S>,其中S列可能因列而异.

单元格值工厂是一个对象,它指定如何从RelationManager对象获取类型的可观察值S.您执行此操作的确切方式取决于您的模型类的设置方式.

如果与给定相关联的各个对象RelationManager永远不会改变(例如,Patient对于给定的RelationManager对象总是相同的),那么它非常简单.假设你有通常的设置Patient:

public class Patient {
    private StringProperty firstName = new SimpleStringProperty(...);
    public StringProperty firstNameProperty() {
        return firstName ;
    }
    public String getFirstName() {
        return firstName.get();
    }
    public void setFirstName(String firstName) {
        this.firstName.set(firstName);
    }
    // etc etc
}
Run Code Online (Sandbox Code Playgroud)

那你就可以做

TableColumn<RelationManager, String> firstNameColumn = new TableColumn<>("First Name");
firstNameColumn.setCellValueFactory(new Callback<CellDataFeatures<RelationManager,String>, ObservableValue<String>>() {
    @Override
    public ObservableValue<String> call(CellDataFeatures<RelationManager, String> data) {
        return data.getValue() // the RelationManager
           .getPatient().firstNameProperty();
    }
});
Run Code Online (Sandbox Code Playgroud)

如果您不使用JavaFX属性,则可以使用与使用相同的后备PropertyValueFactory,即:

TableColumn<RelationManager, String> firstNameColumn = new TableColumn<>("First Name");
firstNameColumn.setCellValueFactory(new Callback<CellDataFeatures<RelationManager,String>, ObservableValue<String>>() {
    @Override
    public ObservableValue<String> call(CellDataFeatures<RelationManager, String> data) {
        return new ReadOnlyStringWrapper(data.getValue().getPatient().getFirstName());
    }
});
Run Code Online (Sandbox Code Playgroud)

但请注意,如果您在桌子外部更改患者姓名,则不会更新.

但是,如果与关系管理器关联的患者对象发生更改(单元仍将观察到错误firstNameProperty()),则这些都不起作用.在这种情况下,您需要一个可观察的值,当"中间"患者属性或firstNameProperty更改时,该值会发生变化.JavaFX有一个BindingsAPI,其中包含一些select(...)可以执行此操作的方法:遗憾的是,在JavaFX 8中,如果沿途的任何对象为null,它们将在TableView上下文中向控制台发出大量警告.在这种情况下,我建议您查看EasyBind框架,它允许您执行类似的操作

firstNameColumn.setCellValueFactory( data -> 
    EasyBind.select(data.getValue().patientProperty())
        .selectObject(Patient::firstNameProperty));
Run Code Online (Sandbox Code Playgroud)

(EasyBind需要JavaFX 8,所以如果你使用它,你也可以使用lambda表达式和方法引用:).

在任何一种情况下,如果您希望表格是可编辑的,那么对于可编辑单元格,在布线编辑方面需要做一些额外的工作,提交回适当的调用以设置属性.