【问题标题】:javafx: keep oldValue and newValue of listview the same when condition has not been fullfilledjavafx:当条件尚未满足时,保持 listview 的 oldValue 和 newValue 相同
【发布时间】:2019-02-10 13:38:44
【问题描述】:

我有一个列表视图,我可以在其中选择将显示在主窗格中的不同窗格。现在对于一个特定的窗格,我需要一些对象来使用每个功能。在列表视图上,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
        }
    });
}

【问题讨论】:

    标签: java javafx


    【解决方案1】:

    这是第一个代码 sn-p 中的可运行示例,第二个 sn-p 是它在您的程序中的样子

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

    【讨论】:

      【解决方案2】:

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

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

      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();
      }
      

      【讨论】:

        猜你喜欢
        • 2015-08-02
        • 2021-05-19
        • 1970-01-01
        • 2018-06-29
        • 1970-01-01
        • 2018-07-27
        • 2020-08-18
        • 1970-01-01
        • 2021-06-09
        相关资源
        最近更新 更多