listview属性_属性提取器:获取ListView即时更新其元素的最佳方法

listview属性

这篇文章是关于如何处理JavaFX ListViews和TableViews的,以及如何通过这些控件了解所包含元素的更改内容。 我想知道为什么在相关书籍中没有找到关于以下模式的任何信息,因为这是一个非常关键的机制。 那里的许多帖子建议通过调用以下命令来强制触发ChangeEvent以刷新ListView:

list.remove(POJO);
list.add(index,POJO);

每次提交更改后! rr!

但是有更好的方法:

通过提供属性提取器,使列表能够报告元素上的更改。

演示应用

我创建了一个小型演示应用程序,可以尝试一下。 基本上,两个TableView和一个ListView共享相同的数据。 要更改元素的属性,一个TableView是可编辑的:

PropertiesExtractor-Demo1

数据模型

强制性PersonBean遵循JavaFX Bean Pattern / Convention
public class PersonBean {

    private StringProperty firstName;
    private StringProperty lastName;
    private ObjectProperty<LocalDate> birthday;
    private ObjectBinding<Long> age;

    public PersonBean() {
    }

    public PersonBean(String firstName, String lastName, LocalDate birthday) {
        setFirstName(firstName);
        setLastName(lastName);
        setBirthday(birthday);
    }

    public final StringProperty firstNameProperty() {
        if (firstName == null) {
            firstName = new SimpleStringProperty();
        }
        return firstName;
    }

    public final String getFirstName() {
        return firstNameProperty().get();
    }

    public final void setFirstName(final java.lang.String firstName) {
        firstNameProperty().set(firstName);
    }

    public final StringProperty lastNameProperty() {
        if (lastName == null) {
            lastName = new SimpleStringProperty();
        }
        return lastName;
    }

    public final java.lang.String getLastName() {
        return lastNameProperty().get();
    }

    public final void setLastName(final java.lang.String lastName) {
        lastNameProperty().set(lastName);
    }

    public final ObjectProperty<LocalDate> birthdayProperty() {
        if (birthday == null) {
            birthday = new SimpleObjectProperty<>();
        }
        return birthday;
    }

    public final LocalDate getBirthday() {
        return birthdayProperty().get();
    }

    public final void setBirthday(final java.time.LocalDate birthday) {
        birthdayProperty().set(birthday);

    }

    public String stringValue() {
        return String.format("%s %s %s", getFirstName(), getLastName(), getBirthday().format(DateTimeFormatter.ISO_LOCAL_DATE));
    }

    public final ObjectBinding<Long> ageBinding() {
        if (age == null) {
            age = new ObjectBinding<Long>() {
                {
                    bind(birthdayProperty());
                }

                @Override
                protected Long computeValue() {
                    if (getBirthday() == null) {
                        return null;
                    }
                    return getBirthday().until(LocalDate.now(), ChronoUnit.YEARS);
                }
            };
        }
        return age;
    }

    public static Callback<PersonBean, Observable[]> extractor() {
        return (PersonBean p) -> new Observable[]{p.lastNameProperty(), p.firstNameProperty(), p.birthdayProperty(), p.ageBinding()};
    }
}

包含随机创建的PersonBean列表的DataModel:

public class DataModel {

    private ObservableList<PersonBean> personFXBeans;

    public DataModel() {
        init();
    }

    private void init() {
        personFXBeans = DataSource.getRandomPersonBeansList(100);
    }

    public ObservableList<PersonBean> getPersonFXBeans() {
        return personFXBeans;
    }
}

您可能知道要在JavaFX中将DataModel例如分配给TableView或ListView,您只需要使用setItems(ObvervableList)方法。

@FXML
public void onFillWithDemoDataFXBeans() {
  readOnlyListView.setItems(model.getPersonFXBeans());
  readOnlyTableView.setItems(model.getPersonFXBeans());
  editableTableView.setItems(model.getPersonFXBeans());
}

现在已经通过两种方式通过绑定来完成有关包含元素的属性更改的TableView的通知:通过PropertyValueFactory或通过或多或少的直接属性绑定:

readOnlyFirstNameColumn.setCellValueFactory(new PropertyValueFactory<>("firstName"));
readOnlyLastNameColumn.setCellValueFactory(new PropertyValueFactory<>("lastName"));
readOnlyBirthdayColumn.setCellValueFactory(new PropertyValueFactory<>("birthday"));
readOnlyAgeColumn.setCellValueFactory(i -> i.getValue().ageBinding());

editableFirstNameColumn.setCellValueFactory(i -> i.getValue().firstNameProperty());
editableLastNameColumn.setCellValueFactory(i -> i.getValue().lastNameProperty());
editableBirthdayColumn.setCellValueFactory(i -> i.getValue().birthdayProperty());
ageColumn.setCellValueFactory(i -> i.getValue().ageBinding());

但是ListView基本上只观察列表,而不观察列表中每个元素的属性。

当使用由FXCollections.observableArrayList()创建的ObservableList时,ListView将仅在ListChange事件上刷新,例如remove()元素的add()。 因此:

list.remove(POJO);
list.add(index,POJO);

每次提交更改后。

但是有更好的方法:

通过提供属性提取器,使列表能够报告元素上的更改。 那您就不必担心刷新了!

ObservableList person = FXCollections.observableArrayList( PersonBean.extractor() );

请参见DataSource.getRandomPersonBeansList(int length)

public static ObservableList<PersonBean> getRandomPersonBeansList(int length) {
        ObservableList<PersonBean> persons = FXCollections.observableArrayList(PersonBean.extractor());
        for (int i = 0; i < length; i++) {
            persons.add(new PersonBean(getRandomName(), getRandomLastname(), getRandomLocalDate()));
        }
        return persons;
    }

这个Extrator基本上是一个Callback,其中包含Obvervable数组,然后由Obervablelist观察(更精确的是:ObservableListWrapper):

我的PersonBean已经提供了Extrator回调:

public static Callback<PersonBean, Observable[]> extractor() {
   return (PersonBean p) -> new Observable[]{p.lastNameProperty(), p.firstNameProperty(), p.birthdayProperty(), p.ageBinding()};
}

按照此模式,所有控件在应用更改后都会立即更新。

编辑资料...

PropertiesExtractor-Demo3

并提交:

PropertiesExtractor-Demo4

请输入密码!

您可以在我的BitBucket存储库中找到完整的代码。

翻译自: https://www.javacodegeeks.com/2014/11/properties-extractor-best-way-to-get-the-listview-instantly-updating-its-elements.html

listview属性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值