如何定义ListView应该用于呈现的属性

时间:2014-07-06 16:24:42

标签: java listview javafx

我有一个java bean对象列表,我想在ListView控件中显示。默认情况下,ListView使用toString方法。

如何在ListView中定义用于渲染的属性?

我希望在此代码中通过PropertyValueFactory实现与TableView相同的功能:

@FXML
private TableView<Person> mainTableView;
//...
TableColumn<Person,String> personColumn = new TableColumn<>("Name");List
personColumn.setCellValueFactory(new PropertyValueFactory("name"));
mainTableView.getColumns().add(personColumn);

修改

看起来没有简单的(开箱即用)解决方案。根据James_D的代码,我创建了泛型类来处理问题。它包装了PropertyValueFactory - 请注意,PropertyValueFactory首先查找方法[NAME] Property(),试图获得可观察性,只有在未找到它时才会尝试访问标准bean属性。

public class PropertyValueFactoryWrapperCellFactory<T> implements Callback<ListView<T>, ListCell<T>> {

    private final PropertyValueFactory<T, String> pvf;

    public PropertyValueFactoryWrapperCellFactory(String propertyName) {
        super();
        pvf = new PropertyValueFactory(propertyName);
    }

    @Override
    public ListCell<T> call(ListView<T> param) {
        return new ListCell<T>() {
            @Override
            public void updateItem(T item, boolean empty) {
                super.updateItem(item, empty);
                textProperty().unbind();
                if (item == null) {
                    return;
                }
                TableColumn.CellDataFeatures<T, String> cdf = new TableColumn.CellDataFeatures<>(null, null, item);
                textProperty().bind(pvf.call(cdf));
            }
        };
    }

}

用法:

@FXML
private ListView<Person> mainListView;
//...
mainListView.setCellFactory(new PropertyValueFactoryWrapperCellFactory("name"));

2 个答案:

答案 0 :(得分:4)

使用细胞工厂。

如果属性是不可变的,那就很简单了:

ListView<MyDataType> listView = new ListView<>();
listView.setCellFactory(new Callback<ListView<MyDataType>, ListCell<MyDataType>>() {
    @Override
    public ListCell<MyDataType> call(ListView<MyDataType> lv) {
        return new ListCell<MyDataType>() {
            @Override
            public void updateItem(MyDataType item, boolean empty) {
                super.updateItem(item, empty);
                if (item == null) {
                    setText(null);
                } else {
                    // assume MyDataType.getSomeProperty() returns a string
                    setText(item.getSomeProperty());
                }
            }
        };
    }
});

如果属性可以更改其值并且列表视图需要动态更新以响应这些更改,则需要绑定列表单元格的textProperty

listView.setCellFactory(new Callback<ListView<MyDataType>, ListCell<MyDataType>>() {
    @Override
    public ListCell<MyDataType> call(ListView<MyDataType> lv) {
        return new ListCell<MyDataType>() {
            @Override
            public void updateItem(MyDataType item, boolean empty) {
                super.updateItem(item, empty);
                textProperty().unbind();
                if (item != null) {
                    // assumes MyDataType.someProperty() returns a StringProperty:
                    textProperty.bind(item.someProperty());
                }
            }
        };
    }
});

答案 1 :(得分:1)

绑定字符串属性

此代码允许您选择ListView中显示的JavaFX属性。我在lambda中使用一个匿名类来为正在发生的事情添加一些清晰度。在这个例子中:

  • 显示 - ListView背后的基础对象
  • titleProperty - 要显示的JavaFX属性
listView.setCellFactory( 
    listview -> { 
        return new ListCell<Display>() {
            @Override
            public void updateItem(Display item, boolean empty) {
                super.updateItem(item, empty);
                textProperty().unbind();
                if(item != null)
                    textProperty().bind(item.titleProperty());
                else
                    setText(null);
            }
        };
    }
);

说明

使用此代码,我们基本上是自定义ListCell。更新时,显示的项目为null,我们清除显示文本。否则,我们将文本设置为项目的title属性。

TL; DR ::修改James_D的解决方案

我的基础是James_D的第二个例子。我想将SimpleStringProperty绑定为ListView中显示的文本。 James_D的解决方案工作得很好,但是当我从ListView中的ObservableList删除一个对象时没有更新,所以我修改了它。我也认为有一个更清洁的lambda例子会很好。