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对象.
最好,西蒙.
有关如何执行此操作的具体细节取决于您的要求:例如,对于给定的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表达式和方法引用:).
在任何一种情况下,如果您希望表格是可编辑的,那么对于可编辑单元格,在布线编辑方面需要做一些额外的工作,提交回适当的调用以设置属性.