TableView with different objects (javafx)

前端 未结 1 2008
南方客
南方客 2021-01-15 07:06

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 t

相关标签:
1条回答
  • 2021-01-15 08:04

    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?

    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.

    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.

    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
    }
    

    then you can just do

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

    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.

    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 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.

    0 讨论(0)
提交回复
热议问题