当 JRE6 JavaFX2.2 上的 ObservableList 更改时,JavaFX ListView 不会更新

JavaFX ListView isn't updated when ObservableList changes on JRE6 JavaFX2.2

我的问题是 ListView(复选框列表视图)在 ObservableList 更改时没有更新。

此问题仅在我使用过时版本的 JavaFX 和过时 JRE(jre6 和 jfx2.2)时发生。当我使用 jre8 和它包含的 JavaFX 时,问题消失了,列表刷新得很好。

上述最新 JavaFX 的工作源代码:

榜单:

public ObservableList<TestCaseCheckboxModel> TestCases;

//Constructor
public SessionTestCaseModel() {
    TestCases = FXCollections.observableArrayList(new Callback<TestCaseCheckboxModel, Observable[]>(){
        @Override
        public Observable[] call(TestCaseCheckboxModel model) {
            return new Observable[]{model.TestCaseName, model.TestCaseStatus, model.TestCaseSelected};//selected might not be needed since it's bound to the listview anyways
        }
    });
}

列表使用的 Class 具有以下属性:

public StringProperty TestCaseName = new SimpleStringProperty();
public IntegerProperty TestCaseStatus = new SimpleIntegerProperty();
public BooleanProperty TestCaseSelected = new SimpleBooleanProperty();

列表是在外部填充的。

ListView:

@FXML
private ListView<TestCaseCheckboxModel> testcaseListView;

//bind the checkbox select to the model property
testcaseListView.setCellFactory(CheckBoxListCell.forListView(new Callback<TestCaseCheckboxModel, ObservableValue<Boolean>>() {
   @Override
   public ObservableValue<Boolean> call(TestCaseCheckboxModel item) {
        return item.TestCaseSelected;
    }
}));

//initiate the checkbox list view with the model items
testcaseListView.setItems(getModel().TestCases);

问题是当我更改列表项时,ListView 在旧的 JavaFX 版本上不会更改。

可能值得一提的是,在我 add/remove 列表中的项目之后,列表中的项目会更新(就像它们本身发生变化时应该发生的那样)。但是,据我所知,无论如何调用列表的 add 函数都会触发 ListView 更新。

另一方面,当项目属性发生变化时,这将触发新旧 JavaFX 版本,因此 Callback 提取器按预期工作:

getModel().TestCases.addListener(new ListChangeListener<TestCaseCheckboxModel>(){
         @Override
            public void onChanged(Change change) {
                System.out.println(change);
        }
    });

是否有已知的解决方法?

感谢您的帮助。

在此线程的帮助下回答我自己的问题:

我实现了一个能够更新 ListView 的自定义 ListViewSkin "from the inside":

public class UpdateableListViewSkin<T> extends ListViewSkin<T> {

    public UpdateableListViewSkin(ListView<T> arg0) {
        super(arg0);
    }

    public void refresh() {
        super.flow.recreateCells();
    }

}

然后我将 ObservableList 添加到 ListView,实例化 Skin 并将其设置为 ListView

//initiate the checkbox list view with the model items
testcaseListView.setItems(getModel().TestCases);

UpdateableListViewSkin<TestCaseCheckboxModel> skin = new UpdateableListViewSkin<TestCaseCheckboxModel>(testcaseListView);
testcaseListView.setSkin(skin);

关键是你需要给ObservableList添加一个有效的onChange监听器,它会触发Skin.refresh()方法。我在将 Skin 设置为 ListView:

后立即执行此操作
getModel().TestCases.addListener(new ListChangeListener<TestCaseCheckboxModel>(){
    @SuppressWarnings("unchecked")
    @Override
        public void onChanged(Change change) {
            ((UpdateableListViewSkin<TestCaseCheckboxModel>)testcaseListView.getSkin()).refresh();
        }
    });

此解决方法会触发 ListView 的更新功能,就像在新版本的 JavaFX 上一样。