TableView与不同的对象(javafx) [英] TableView with different objects (javafx)

查看:130
本文介绍了TableView与不同的对象(javafx)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Im currently developing a application for watching who is responsible for different Patients, however i havent been able to solve how to fill a table with different object types.

是我的TableView控制器的代码。 TableView将以四种不同的对象类型结束,所有这些都将从数据库中检索。

Below is my code for my TableView controller. The TableView will end up with four different object typs, all will be retrieved from a database.

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

I want my table to hold Patient objects, User objects (responsible) and a RelationManager object.

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

Below is my code, if you need more of the code, please let me know :-).

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

relationData是返回的RelationManager对象。该对象包含一个User对象,一个Patient对象和一个Responsible对象。

relationData is a RelationManager object returned. This object contains a User object, a Patient object and a Responsible object.

Best,
Simon。

Best, Simon.

推荐答案

有关如何执行此操作的具体细节取决于您的要求:例如,对于给定的RelationManager对象,请执行用户与之相关的,患者或负责任的物体是否会发生变化?你需要表格是否可编辑?

The exact details of how you do this depend on your requirements: for example, for a given RelationManager object, do the User, Patient, or Responsible objects associated with it ever change? Do you need the table to be editable?

但基本思路是表格中的每一行代表一些RelationManager,因此表格类型为的TableView< RelationManager> 。每列显示某种类型的值(称之为 S ),因此每列的类型为 TableColumn< RelationManager,S> ,其中 S 可能因列而异。

But the basic idea is that each row in the table represents some RelationManager, so the table type is TableView<RelationManager>. Each column displays a value of some type (call it S), so each column is of type TableColumn<RelationManager, S>, where S might vary from one column to the next.

单元格值工厂是一个对象指定如何从 RelationManager 对象获取类型 S 的可观察值。这样做的确切方式取决于模型类的设置方式。

The cell value factory is an object that specifies how to get from the RelationManager object to an observable value of type S. The exact way you do this depends on how your model classes are set up.

如果与给定的 RelationManager 永远不会改变(例如 Patient 对于给定的 RelationManager 总是相同的),那么它非常简单。假设您有患者的常规设置

If the individual objects associated with a given RelationManager never change (e.g. the Patient for a given RelationManager is always the same), then it's pretty straightforward. Assuming you have the usual setup for 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
}

那么你可以只需执行

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

如果您不使用JavaFX属性,则可以使用与 PropertyValueFactory 使用,即:

If you are not using JavaFX properties, you can use the same fallback that the PropertyValueFactory uses, i.e.:

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

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

but note that this won't update if you change the name of the patient externally to the table.

但是,如果与关系管理器关联的患者对象发生更改(单元格仍然会观察到错误的 firstNameProperty),则这些都不起作用( ))。在这种情况下,您需要一个可观察的值,当中间患者属性或firstNameProperty更改时,该值会发生变化。 JavaFX有一个 Bindings 带有一些 select(...)的API可以做到这一点:不幸的是,在JavaFX 8中,他们向控制台发出了大量警告,如果有的话沿途的对象为null,它们将位于 TableView 上下文中。在这种情况下,我建议您查看 EasyBind 框架,它允许您执行类似

However, none of this will work if the patient object associated with the relation manager is changed (the cell will still be observing the wrong firstNameProperty()). In that case you need an observable value that changes when either the "intermediate" patient property or the firstNameProperty change. JavaFX has a Bindings API with some select(...) methods that can do this: unfortunately in JavaFX 8 they spew out enormous amounts of warnings to the console if any of the objects along the way are null, which they will be in a TableView context. In this case I would recommend looking at the EasyBind framework, which will allow you to do something like

firstNameColumn.setCellValueFactory( data -> 
    EasyBind.select(data.getValue().patientProperty())
        .selectObject(Patient::firstNameProperty));

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

(EasyBind requires JavaFX 8, so you if you get to use it, you also get to use lambda expressions and method references :).)

在任何一种情况下,如果你想让表格可编辑,那么对于可编辑单元格来说,还有一些额外的工作要做。布线编辑提交回适当的调用以设置属性。

In either case, if you want the table to be editable, there's a little extra work to do for the editable cells in terms of wiring editing commits back to the appropriate call to set a property.

这篇关于TableView与不同的对象(javafx)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆