javafx:当条件尚未满足时,保持listview的oldValue和newValue相同

时间:2018-09-05 11:59:46

标签: java javafx

我有一个列表视图,可以在其中选择将显示在主窗格中的不同窗格。现在,对于特定的窗格,我需要一些对象来使用每个功能。在列表视图上,selectedItemProperty上有一个侦听器。我想检查所需的对象是否可用,否则对象oldValue和newValue应该保留其值。有办法吗?

listView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>()
{
    @Override
    public void changed(ObservableValue<? extends Object> observable, Object oldValue,
                            Object newValue)
    {
        if(obj == null)
        {
            // keep the oldValues for both
        }
    });
}

2 个答案:

答案 0 :(得分:0)

这是第一个代码段中的一个可运行示例,第二个代码段是程序中的外观

public class MainNoFXML extends Application {

    public static void main(String[] args) { launch(args); }

    @Override
    public void start(Stage primaryStage) {
        ListView<Object> listView = new ListView<>(FXCollections.observableArrayList(new String[]{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"}));
        listView.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal)->{
            if(newVal != null && (!newVal.equals("Monday") && !newVal.equals("Tuesday")))
                Platform.runLater(() -> listView.getSelectionModel().select(oldVal));
        });

        Scene scene = new Scene(listView);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

您的程序(我认为这是正确的,不能完全确定您的工作方式)

listView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
        @Override
        public void changed(ObservableValue<? extends Object> observable, Object oldValue,
                            Object newValue)
        {
            if(obj == null)
            {
                Platform.runLater(() -> listView.getSelectionModel().select(oldValue));
                // keep the oldValues for both
            }
        });
    });

答案 1 :(得分:0)

在这种情况下,您应该使用自定义选择模型来防止选择某些项目。

简化了以下实现。它不处理项目列表的更改。此外,它仅实现单一选择,但希望它显示了通用方法:

public class CustomSelectionModel<T> extends MultipleSelectionModel<T> {

    private final ListView<T> listView;
    private final ObservableList<Integer> selectedIndices = FXCollections.observableArrayList();
    private final ObservableList<Integer> selectedIndicesUnmodifiable = FXCollections.unmodifiableObservableList(selectedIndices);
    private final ObservableList<T> selectedItems;

    private BiPredicate<Integer, T> leavePredicate;
    private BiPredicate<Integer, T> enterPredicate;

    public BiPredicate<Integer, T> getLeavePredicate() {
        return leavePredicate;
    }

    public void setLeavePredicate(BiPredicate<Integer, T> leavePredicate) {
        this.leavePredicate = leavePredicate;
    }

    public BiPredicate<Integer, T> getEnterPredicate() {
        return enterPredicate;
    }

    public void setEnterPredicate(BiPredicate<Integer, T> enterPredicate) {
        this.enterPredicate = enterPredicate;
    }

    public CustomSelectionModel(ListView<T> listView) {
        if (listView == null) {
            throw new IllegalArgumentException();
        }
        this.listView = listView;
        this.selectedItems = new TransformationList<T, Integer>(selectedIndices) {

            @Override
            protected void sourceChanged(ListChangeListener.Change<? extends Integer> c) {
                beginChange();
                while (c.next()) {
                    if (c.wasReplaced()) {
                        nextReplace(c.getFrom(), c.getTo(), c.getRemoved().stream().map(listView.getItems()::get).collect(Collectors.toList()));
                    } else if (c.wasRemoved()) {
                        nextRemove(c.getFrom(), c.getRemoved().stream().map(listView.getItems()::get).collect(Collectors.toList()));
                    } else if (c.wasAdded()) {
                        nextAdd(c.getFrom(), c.getTo());
                    }
                }
                endChange();
            }

            @Override
            public int getSourceIndex(int index) {
                return index;
            }

            @Override
            public T get(int index) {
                return listView.getItems().get(getSource().get(index));
            }

            @Override
            public int size() {
                return getSource().size();
            }

        };
    }

    @Override
    public ObservableList<Integer> getSelectedIndices() {
        return selectedIndicesUnmodifiable;
    }

    @Override
    public ObservableList<T> getSelectedItems() {
        return selectedItems;
    }

    @Override
    public void selectIndices(int index, int... indices) {
        clearAndSelect(index); // ignore all indices but the first
    }

    @Override
    public void selectAll() {
        selectFirst();
    }

    @Override
    public void selectFirst() {
        if (!listView.getItems().isEmpty()) {
            clearAndSelect(0);
        }
    }

    @Override
    public void selectLast() {
        if (!listView.getItems().isEmpty()) {
            clearAndSelect(listView.getItems().size() - 1);
        }
    }

    private void moveSelection(int oldIndex, int newIndex) {
        if ((leavePredicate == null || leavePredicate.test(oldIndex, oldIndex == -1 ? null : listView.getItems().get(oldIndex)))
                && (enterPredicate == null || enterPredicate.test(newIndex, newIndex == -1 ? null : listView.getItems().get(newIndex)))) {
            setSelectedIndex(newIndex);
            if (newIndex == -1) {
                selectedItems.clear();
                setSelectedItem(null);
            } else {
                setSelectedItem(listView.getItems().get(newIndex));
                if (isEmpty()) {
                    selectedIndices.add(newIndex);
                } else {
                    selectedIndices.set(0, newIndex);
                }
            }
            listView.getFocusModel().focus(newIndex);
        }
    }

    @Override
    public void clearAndSelect(int index) {
        moveSelection(getSelectedIndex(), index);
    }

    @Override
    public void select(int index) {
        clearAndSelect(index);
    }

    @Override
    public void select(T obj) {
        int index = listView.getItems().indexOf(obj);
        if (index >= 0) {
            clearAndSelect(index);
        }
    }

    @Override
    public void clearSelection(int index) {
        if (getSelectedIndex() == index) {
            clearSelection();
        }
    }

    @Override
    public void clearSelection() {
        moveSelection(getSelectedIndex(), -1);
    }

    @Override
    public boolean isSelected(int index) {
        return selectedIndices.contains(index);
    }

    @Override
    public boolean isEmpty() {
        return selectedIndices.isEmpty();
    }

    @Override
    public void selectPrevious() {
        int index = getSelectedIndex() - 1;
        if (index >= 0) {
            clearAndSelect(index);
        }
    }

    @Override
    public void selectNext() {
        int index = getSelectedIndex() + 1;
        if (index < listView.getItems().size()) {
            clearAndSelect(index);
        }
    }

}
@Override
public void start(Stage primaryStage) throws Exception {
    ListView<Integer> listView = new ListView<>();

    for (int i = 0; i < 100; i++) {
        listView.getItems().add(i);
    }

    CustomSelectionModel<Integer> selectionModel = new CustomSelectionModel<>(listView);
    listView.setSelectionModel(selectionModel);

    CheckBox moveAllowed = new CheckBox("disallow movement");
    moveAllowed.selectedProperty().addListener((o, oldValue, newValue) -> selectionModel.setLeavePredicate(newValue ? (index, item) -> false : null));

    CheckBox enterOdd = new CheckBox("enter odd items disallowed");
    enterOdd.selectedProperty().addListener((o, oldValue, newValue) -> selectionModel.setEnterPredicate(newValue ? (index, item) -> (index & 1) == 0 : null));

    Scene scene = new Scene(new ScrollPane(new HBox(listView, new VBox(moveAllowed, enterOdd))));

    primaryStage.setScene(scene);
    primaryStage.show();
}