装饰ObservableList并保留更改事件的最佳实践

装饰ObservableList并保留更改事件的最佳实践,第1张

装饰ObservableList并保留更改事件的最佳实践

自您发布以来,我一直在考虑这一点。我在注释中建议的使用EasyBind无效,因为

Warning
每次您
get(...)
映射列表上调用时,它都会创建一个新的。所以

stringList.add("foo");warningList.get(0).setChecked(true);assert warningList.get(0).isChecked();

会失败。

此外,如果您在源列表(

stringList
)中有重复的条目,则您的机制会出错(我认为),因为
warningList
当从中删除单个元素时,您将从删除所有对应的条目
stringList
。实际上,正确地删除元素非常棘手。

这是一个基于Tomas
Mikula的解决方案,

MappedList
它缓存了源元素和被映射元素之间的映射。它使用
IdentityHashMap
来确保两个列表中重复元素的行为正确。请注意,这仅适用于在将项目添加到源列表时要创建新对象的特定情况,因此,不能(也不能)代替EasyBind中的机制。

import java.util.ArrayList;import java.util.IdentityHashMap;import java.util.List;import java.util.function.Function;import javafx.application.Application;import javafx.beans.property.BooleanProperty;import javafx.beans.property.ReadOnlyStringProperty;import javafx.beans.property.ReadOnlyStringWrapper;import javafx.beans.property.SimpleBooleanProperty;import javafx.collections.FXCollections;import javafx.collections.ListChangeListener.Change;import javafx.collections.ObservableList;import javafx.collections.transformation.TransformationList;import javafx.geometry.Insets;import javafx.scene.Scene;import javafx.scene.control.Button;import javafx.scene.control.ListView;import javafx.scene.control.TextField;import javafx.scene.control.cell.CheckBoxListCell;import javafx.scene.layout.HBox;import javafx.scene.layout.VBox;import javafx.stage.Stage;public class WrappedObjectListExample extends Application {    @Override    public void start(Stage primaryStage) {        ObservableList<String> stringList = FXCollections.observableArrayList("One", "Two", "Three");        ObservableList<Warning> warningList = new CachingMappedList<Warning, String>(stringList, Warning::new);        ListView<String> stringListView = new ListView<>(stringList);        ListView<Warning> warningListView = new ListView<>(warningList);        warningListView.setCellFactory(CheckBoxListCell.forListView(Warning::checkedProperty));        TextField textField = new TextField();        textField.setonAction(e -> { if (! textField.getText().isEmpty()) {     stringList.add(textField.getText());     textField.setText(""); }        });        Button remove = new Button("Remove");        remove.setonAction(e -> stringList.remove(stringListView.getSelectionModel().getSelectedIndex()));        remove.disableProperty().bind(stringListView.getSelectionModel().selectedItemProperty().isNull());        HBox lists = new HBox(10, stringListView, warningListView);        VBox root = new VBox(10, lists, textField, remove);        root.setPadding(new Insets(20));        primaryStage.setScene(new Scene(root));        primaryStage.show();    }    public static class Warning {        private final ReadonlyStringWrapper name = new ReadonlyStringWrapper();        private final BooleanProperty checked = new SimpleBooleanProperty();        public Warning(String name) { this.name.set(name);        }        public final ReadonlyStringProperty nameProperty() { return this.name.getReadonlyProperty();        }        public final String getName() { return this.nameProperty().get();        }        public final BooleanProperty checkedProperty() { return this.checked;        }        public final boolean isChecked() { return this.checkedProperty().get();        }        public final void setChecked(final boolean checked) { this.checkedProperty().set(checked);        }        @Override        public String toString() { return getName();        }    }    public static class CachingMappedList<S,T> extends TransformationList<S, T> {        private final Function<T, S> mapper ;        private final IdentityHashMap<T, S> cache ;        public CachingMappedList(ObservableList<T> source, Function<T,S> mapper) { super(source); this.mapper = mapper ; this.cache = new IdentityHashMap<>();        }        @Override        protected void sourceChanged(Change<? extends T> c) { fireChange(new Change<S>(this) {     @Override     public boolean wasAdded() {         return c.wasAdded();     }     @Override     public boolean wasRemoved() {         return c.wasRemoved();     }     @Override     public boolean wasReplaced() {         return c.wasReplaced();     }     @Override     public boolean wasUpdated() {         return c.wasUpdated();     }     @Override     public boolean wasPermutated() {         return c.wasPermutated();     }     @Override     public boolean next() {         return c.next();     }     @Override     public void reset() {         c.reset();     }     @Override     public int getFrom() {         return c.getFrom();     }     @Override     public int getTo() {         return c.getTo();     }     @Override     public List<S> getRemoved() {         List<S> removed = new ArrayList<>();         c.getRemoved().forEach(t -> removed.add(cache.get(t)));         return removed;     }     @Override     public int getPermutation(int i) {         return c.getPermutation(i);     }     @Override     protected int[] getPermutation() {         throw new AssertionError("Unreachable pre");     } }); // clean up cache: c.reset(); while (c.next()) {     if (c.wasRemoved()) {         c.getRemoved().forEach(cache::remove);     } }         }        @Override        public int getSourceIndex(int index) { return index ;        }        @Override        public S get(int index) { return cache.computeIfAbsent(getSource().get(index), mapper);        }        @Override        public int size() { return getSource().size();        }    }    public static void main(String[] args) {        launch(args);    }}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5615691.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存