当并非所有属性都在同一个类中时,填充JavaFX表视图

时间:2013-10-06 13:04:20

标签: java properties javafx tableview fxml

我有一个关于在JavaFX中填充TableViews的问题。 首先,我是javaFX的新手,因为我的无知。

我做了一个简单的例子来试验tableview的工作原理:

public class Person{

    private StringProperty firstName, lastName;
    private IntegerProperty age;

    //Left the constructor and getters out

}

对于控制器:

public class Controller implements Initializable {

    @FXML private TableView tableView;
    @FXML private TableColumn firstNameColumn, lastNameColumn, ageColumn;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        ObservableList<Person> data = FXCollections.observableArrayList();        
        tableView.setItems(data);

        firstNameColumn.setCellFactory(new PropertyValueFactory<Person, String>("firstName"));
        lastNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
        ageColumn.setCellValueFactory(new PropertyValueFactory<Person, Integer>("age"));

        data.add(new Person("Piet", "Jansen", 22));
    }
}

这样可以正常工作,但如果每个人都有一个包含名字和姓氏的Name对象呢?

e.g:

public class Person{

    private Name name;
    private IntegerProperty age;

    //Left the constructor and getters out

}

名称类:

public class Name {

    private StringProperty firstName, lastName;

    public Name(String firstName, String lastName) {
        this.firstName = new SimpleStringProperty(firstName);
        this.lastName = new SimpleStringProperty(lastName);
    }

    public String getFirstName() {
        return firstName.get();
    }

    public StringProperty firstNameProperty() {
        return firstName;
    }

    public String getLastName() {
        return lastName.get();
    }

    public StringProperty lastNameProperty() {
        return lastName;
    }
}

提前致谢:)

2 个答案:

答案 0 :(得分:4)

通过假设列不可编辑,您始终可以自定义在列视图呈现中显示基础模型类的属性或属性组合的内容和方式。例如,对于给定的Person模型类,您可以在tableView的一列中显示其所有属性(lastname,firstname,age等)。请遵循以下代码:

TableColumn nameCol = new TableColumn("First and Last Name");
nameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, String>, ObservableValue<String>>() {
    @Override
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Person, String> p) {
        // p.getValue() returns the Person instance for a particular TableView row
        return p.getValue().getName().firstNameProperty().concat(" - ").concat(p.getValue().getName().lastNameProperty());
        // and concating maybe other attributes like: p.getValue().getOrganization().getCity().idenNumberProperty(); etc.
    }
});

如果类名称具有常规属性,如

private String firstName;
private String lastName;

而不是JavaFX的SimpleStringProperty,然后

TableColumn nameCol = new TableColumn("First and Last Name");
nameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, String>, ObservableValue<String>>() {
    @Override
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Person, String> p) {
        return new SimpleStringProperty(p.getValue().getName().getFirstName() + " - " + p.getValue().getName().getLastName());
    }
});

如果该列可编辑,那么您需要做更多工作,例如解析“名字和姓氏”列项字符串值并将部件设置为onEditCommit()中Name类的相应属性处理程序,例如。

答案 1 :(得分:3)

我看到两种方法可以实现您的目标。 选项1 将确保无论何时设置 Person 类上的 name 字段,它依次将值设置为另外两个< em> SimpleStringProperty 字段,代表名字和姓氏。

public class Person 
{
    private Name name;
    private SimpleStringProperty firstName = new SimpleStringProperty("");
    private SimpleStringProperty lastName = new SimpleStringProperty("");
    private IntegerProperty age;

    public Person(Name name) 
    {
        this.firstName.set(name.getFirstName());
        this.lastName.set(name.getLastName());
    }

    public setName(Name name) 
    {
        this.name = name;
        this.firstName.set(name.getFirstName());
        this.lastName.set(name.getLastName());
    }
}

选项2 将使用单个 SimpleObjectProperty 以及为每个列设置自定义单元工厂。

public class Person 
{
    private SimpleObjectProperty<Name> name = new SimpleObjectProperty<Name>();
    private IntegerProperty age;

    public Person(Name name) 
    {
        this.name.set(name);
    }
}

第一个和最后一个名称列的单元格值工厂将指向 Person 对象上的相同字段( name ),但您将为其定义单独的单元工厂每一栏。

firstNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("name"));
lastNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String("name"));

firstNameColumn.setCellFactory(new Callback<TableColumn<Person,Name>,TableCell<Person,Name>>()
{
    @Override
    public TableCell<Person, Name> call(TableColumn<Person,Name> p)
    {
        final TableCell<Person,Name> cell = new TableCell<Person,Name>()
        {
            @Override
            public void updateItem(final Name item, boolean empty)
            {
                super.updateItem(item, empty);
                if (empty)
                {
                    this.setText(""); 
                }
                else
                {
                    this.setText(item.getFirstName());
                }
            }
        };
        return cell;
    }
});

为lastNameColumn设置单元格工厂的方式相同,除了在 updateItem 方法中,您将调用 item.getLastName()作为 setText <的参数/ em>方法。

我希望这个答案很有帮助,让我知道它是否适合你!