从addListener中的ListView中删除项目

时间:2014-12-08 02:45:17

标签: java listview javafx javafx-8

我遇到以下Java程序的问题。我在Ubuntu系统上使用JavaFX和JDK-1.8u25。我想显示一个ListView并从列表中删除突出显示的条目。我创建了一个列表并将其与ObservableList配对以通知侦听器事件。但是,似乎通过删除项目来更改列表," orderOvList.remove(i,i + 1)"在下面,生成另一个侦听器事件。所以,似乎我在侦听器代码的主体中递归。我想过将列表元素从有序列表中移出," orderList.remove(i)"但是然后ListView没有更新。

任何有想法的人?

运行后,下面的代码崩溃了。

堆栈追踪:

0
0
Exception in thread "JavaFX Application Thread" java.lang.UnsupportedOperationException
    at java.util.Collections$UnmodifiableCollection.add(Collections.java:1055)
    at javafx.collections.ListChangeBuilder.nextRemove(ListChangeBuilder.java:204)
    at javafx.collections.ObservableListBase.nextRemove(ObservableListBase.java:150)
    at javafx.collections.ModifiableObservableListBase.remove(ModifiableObservableListBase.java:181)
    at com.sun.javafx.collections.ObservableListWrapper.remove(ObservableListWrapper.java:165)
    at TestListView.lambda$start$0(TestListView.java:32)
    at TestListView$$Lambda$82/921981528.invalidated(Unknown Source)
    at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:176)
    at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:142)
    at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
    at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:145)
    at javafx.scene.control.SelectionModel.setSelectedItem(SelectionModel.java:102)
    at javafx.scene.control.ListView$ListViewBitSetSelectionModel$1.onChanged(ListView.java:1245)
    at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88)
    at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
    at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
    at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
    at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
    at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
    at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
    at com.sun.javafx.collections.ObservableListWrapper.remove(ObservableListWrapper.java:167)
    at TestListView.lambda$start$0(TestListView.java:32)
    at TestListView$$Lambda$82/921981528.invalidated(Unknown Source)
    at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:176)
    at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:142)
    at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
    at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:145)
    at javafx.scene.control.SelectionModel.setSelectedItem(SelectionModel.java:102)
    at javafx.scene.control.MultipleSelectionModelBase.lambda$new$34(MultipleSelectionModelBase.java:67)
    at javafx.scene.control.MultipleSelectionModelBase$$Lambda$75/1274395902.invalidated(Unknown Source)
    at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.beans.property.ReadOnlyIntegerWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:176)
    at javafx.beans.property.ReadOnlyIntegerWrapper.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:142)
    at javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:113)

    at javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:146)
    at javafx.scene.control.SelectionModel.setSelectedIndex(SelectionModel.java:68)
    at javafx.scene.control.MultipleSelectionModelBase.select(MultipleSelectionModelBase.java:357)
    at javafx.scene.control.ListView.lambda$new$156(ListView.java:374)
    at javafx.scene.control.ListView$$Lambda$74/963851926.invalidated(Unknown Source)
    at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:349)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.beans.property.ReadOnlyBooleanPropertyBase.fireValueChangedEvent(ReadOnlyBooleanPropertyBase.java:72)
    at javafx.scene.Node$FocusedProperty.notifyListeners(Node.java:7526)
    at javafx.scene.Scene$13.invalidated(Scene.java:2046)
    at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:111)
    at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:145)
    at javafx.scene.Scene$KeyHandler.setFocusOwner(Scene.java:3891)
    at javafx.scene.Scene$KeyHandler.requestFocus(Scene.java:3938)
    at javafx.scene.Scene$KeyHandler.access$1900(Scene.java:3877)
    at javafx.scene.Scene.requestFocus(Scene.java:2010)
    at javafx.scene.Node.requestFocus(Node.java:7687)
    at com.sun.javafx.scene.traversal.TopMostTraversalEngine.focusAndNotify(TopMostTraversalEngine.java:92)
    at com.sun.javafx.scene.traversal.TopMostTraversalEngine.traverseToFirst(TopMostTraversalEngine.java:110)
    at javafx.scene.Scene.focusInitial(Scene.java:1980)
    at javafx.scene.Scene.access$3200(Scene.java:144)
    at javafx.scene.Scene$ScenePulseListener.focusCleanup(Scene.java:2330)
    at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2351)
    at com.sun.javafx.tk.Toolkit.lambda$runPulse$28(Toolkit.java:314)
    at com.sun.javafx.tk.Toolkit$$Lambda$154/326451107.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:313)
    at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:340)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:451)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:431)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$363(QuantumToolkit.java:298)
    at com.sun.javafx.tk.quantum.QuantumToolkit$$Lambda$46/1868350875.run(Unknown Source)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$null$45(GtkApplication.java:126)
    at com.sun.glass.ui.gtk.GtkApplication$$Lambda$42/584634336.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:745)

示例代码:

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.List;

public class TestListView extends Application {
  @Override
  public void start (Stage stage) {
    List<String> orderList = new ArrayList<String> ();
    ObservableList<String> orderOvList =
      FXCollections.observableList (orderList);
    ListView<String> order = new ListView<String> (orderOvList);

    orderOvList.add ("abc");
    orderOvList.add ("def");
    orderOvList.add ("ghi");
    orderOvList.add ("jkl");

    VBox orderBoxPane = new VBox (6);
    order.getSelectionModel().selectedItemProperty().addListener (
      ov -> {
        int i = order.getSelectionModel ().getSelectedIndex ();

        if (orderOvList.size () >= 0) {
          System.out.println (i);
          orderOvList.remove (i, i + 1);
        }
      });
    orderBoxPane.getChildren ().add (order);

    Scene scene = new Scene (orderBoxPane);
    stage.setTitle ("TestListView");
    stage.setScene (scene);
    stage.show ();
  }
}

1 个答案:

答案 0 :(得分:1)

用户选择后立即删除所选项目似乎是一种想要编码的奇怪用户体验。我不太确定是什么导致您看到的异常,但是您在侦听器中执行的代码将更改所选值,从而导致在选择模型上引发新的更改事件,这当然是正确的。 。 (我原本期望StackOverflowException而不是UnsupportedOperationException。我的猜测是,#34;嵌套&#34;更改为选择模型中所选项目列表导致尝试更改为不可修改的清单。)

如果这确实是您想要的行为,我会在鼠标按下操作方面考虑更多 - 当用户点击它时从列表中删除该项目。您可以通过创建单元工厂并使用您创建的单元格注册鼠标侦听器来执行此操作:

order.setCellFactory(lv -> {
    ListCell<String> cell = new ListCell<String>() {
        @Override
        public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            setText(item);
        }
    };
    cell.setOnMouseClicked(event -> {
        String item = cell.getItem();
        if (item != null) {
            orderOvList.remove(item);

            // ensure nothing selected after removal:
            order.getSelectionModel().clearSelection();
        }
    });
    return cell ;
});