2

我有一个关于在 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 对象怎么办?

例如:

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

提前致谢:)

4

2 回答 2

5

通过假设列不可编辑,您始终可以自定义在列视图渲染中显示什么以及如何显示底层模型类的属性或属性组合。例如,对于给定的 Person 模型类,您可以在 tableView 的一列中显示其所有属性(姓氏、名字、年龄等)。按照代码:

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

如果类 Name 具有常规属性,例如

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

如果该列将是可编辑的,那么您需要做更多的工作,例如解析“First and Last Name”列项 String 值并将部分设置为 Name 类的适当属性,例如在onEditCommit()处理程序中。

于 2013-10-11T17:06:18.013 回答
3

我看到两种方法可以实现你想要做的事情。选项 1将确保无论何时/无论如何设置Person类上的name字段,它都会依次设置其他两个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方法的参数。

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

于 2013-10-11T15:42:58.937 回答