自您发布以来,我一直在考虑这一点。我在注释中建议的使用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); }}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)