java - 在 addListener 中从 ListView 中删除项目

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

最佳答案

用户选择后立即删除所选项目,这对于想要编码来说似乎是一种奇怪的用户体验。我不太确定是什么导致了您看到的异常,但您在监听器中执行的代码确实会更改所选值,从而导致在选择模型上引发新的更改事件。 (我预计会出现 StackOverflowException,而不是 UnsupportedOperationException。我的猜测是,对选择模型中所选项目列表的“嵌套”更改导致尝试更改不可修改的列表。)

如果这确实是您想要的行为,我会更多地将其视为鼠标按下操作 - 当用户单击该项目时从列表中删除该项目。您可以通过创建一个单元工厂并向您创建的单元注册鼠标监听器来完成此操作:

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

关于java - 在 addListener 中从 ListView 中删除项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27350618/

相关文章:

java - JPA 和 Criteria API 特定选择,使用 select 提取

c# - ListViewItem 的组未通过另一个集合保留

android - 更改方向调用 onpageselected 在 oncreateview 之前

javafx shape3d 纹理 : Don't strectch the image

java - Discord OAuth2 重定向 URL 无法使用 JavaFX WebView JDK12 显示

java - 使用 Java 将 json 对象附加到现有 json 文件中

javax.faces.application.ViewExpiredException : During load test

java - android.R.* 的视觉资源?

android - 以与用户手指在布局上移动相同的速度更改相对布局的高度

java - 确定 JavaFX 字体的宽度和高度