栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

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

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

装饰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);    }}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/609558.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号