但是,使用ListView,它是一个不同的故事.除非我关闭框架并再次打开,否则不会立即显示更改.
我的ListView包含ActionSteps.请注意,我使用了Javafx bean属性.
package application.objects; import java.time.LocalDate; import java.util.ArrayList; import java.util.function.IntPredicate; import javafx.beans.property.IntegerProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; public class ActionStep { private StringProperty actionStepID; private ObjectProperty<LocalDate> dateSet,dateFinished; private StringProperty stepName; private IntegerProperty completion; private ArrayList<StepComment> comments; public ActionStep(String name) { actionStepID = new SimpleStringproperty(); stepName = new SimpleStringproperty(); dateSet = new SimpleObjectProperty<LocalDate>(); dateFinished = new SimpleObjectProperty<LocalDate>(); completion = new SimpleIntegerproperty(); stepName.setValue(name); } public void setName(String name) { stepName.setValue(name); } public String getName() { return stepName.getValue(); } public StringProperty stepNameproperty() { return actionStepID; } public void setID(String id) { actionStepID.setValue(id); } public String getID() { return actionStepID.get(); } public StringProperty actionStepIDproperty() { return actionStepID; } public void setCompletion(int percent) { if (percent < 0 || percent > 100) return; completion.set(percent); } public int getCompletion() { return completion.get(); } public IntegerProperty completionproperty() { return completion; } public void setDateSet(LocalDate date) { dateSet.set(date); } public LocalDate getDateSet() { return dateSet.get(); } public ObjectProperty<LocalDate> dateSetproperty() { return dateSet; } public void setDateFinished(LocalDate date) { dateFinished.set(date); } public LocalDate getDateFinished() { return dateFinished.get(); } public ObjectProperty<LocalDate> dateFinishedproperty() { return dateFinished; } public String toString() { return stepNameproperty().get(); } }
我的ListView也使用ObservableList.
@FXML private ListView<ActionStep> actionStepsListView; private ObservableList<ActionStep> listofSteps; listofSteps = FXCollections.observableArrayList(); actionStepsListView.setItems(listofSteps); if (plan != null) { ArrayList<ActionStep> arrayOfSteps = plan.getStepsArrayList(); for (int i = 0; i < arrayOfSteps.size(); i++) listofSteps.add(arrayOfSteps.get(i)); } else plan = new ActionPlan();
为什么对ObservableList所做的更改不会反映在ListView中?我注意到ListView调用每个对象的toString()来在ListView中显示它们的值,而不是将它绑定到它们的Properties.
我究竟做错了什么?我应该覆盖一家细胞工厂吗?
解决方法
您可以创建一个自定义单元工厂来绑定到stepNameproperty(),但它很棘手(您必须确保在updateItem()方法中取消绑定/从旧项中删除侦听器).
但是,更简单的方法是使用带定义提取器的ObservableList.
首先,修复您的方法名称:您发布的代码中存在一些奇怪的不匹配. getX / setX / xProperty方法名称应该都正确匹配.即代替
public void setName(String name) { stepName.setValue(name); } public String getName() { return stepName.getValue(); } public StringProperty stepNameproperty() { return actionStepID; }
你应该有
public final void setName(String name) { stepName.setValue(name); } public final String getName() { return stepName.getValue(); } public StringProperty nameproperty() { return stepName; }
并且类似地用于其他属性访问器方法. (显然,字段的名称可以是你喜欢的任何东西,因为它们是私有的.)Making the get/set methods final is good practice.
然后,create the list with an extractor.提取器是一个函数,它将列表中的每个元素映射到列表将观察到的Observables数组.如果这些值发生变化,它将向列表的观察者发送列表更新.由于ActionStep的toString()方法引用了nameproperty(),因此我假设您希望在nameproperty()更改时更新ListView.所以你想做
listofSteps = FXCollections.observableArrayList( actionStep -> new Observable[] { actionStep.nameproperty() } // the "extractor" ); actionStepsListView.setItems(listofSteps);
请注意,在早期版本的JavaFX 2.2中,ListView没有正确观察更新事件的列表;在Java 8发布之前不久就修复了这个问题(如果我没记错的话).(因为你标记了JavaFX8这个问题,我假设你使用的是Java 8,所以你应该没问题.)
如果您不使用Java 8,则可以使用以下(等效但更详细)代码:
listofSteps = FXCollections.observableArrayList( new Callback<ActionStep,Observable[]>() { @Override public Observable[] call(ActionStep actionStep) { return new Observable[] { actionStep.nameproperty() } ; } }); actionStepListView.setItems(listofSteps);