Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
FULL PRODUCT VERSION : java version "1.8.0_66" Java(TM) SE Runtime Environment (build 1.8.0_66-b17) Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode) ADDITIONAL OS VERSION INFORMATION : Linux knucklepuck 2.6.32-220.el6.x86_64 #1 SMP Tue Dec 6 19:48:22 GMT 2011 x86_64 x86_64 x86_64 GNU/Linux A DESCRIPTION OF THE PROBLEM : An ArrayIndexOutOfBoundsException is thrown on the JavaFX Application Thread when a TreeTableView's selection model is updated in response to a TreeItem being expanded. The TreeTableView is allowing multiple selections, and my application is trying to select all child nodes of a selected TreeItem when that TreeItem is expanded. There is a FilteredList that was created from the `getSelectedItems()` ObservableList of the TreeTableView's selection model. The exception is thrown when updating this FilteredList; removing the FilteredList prevents this exception from happening. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1. Select a non-leaf TreeItem that is a child of the root node in the TreeTableView. 2. Rapidly expand/collapse the selected TreeItem by clicking quickly on the expand icon. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - The FilteredList should be properly updated with the selected items in the TreeTableView. ACTUAL - An ArrayIndexOutOfBoundsException is thrown when expanding/collapsing a selected TreeItem. ERROR MESSAGES/STACK TRACES THAT OCCUR : Change: { [TreeItem [ value: Node 1-1 ]] added at 0 } Change: { [TreeItem [ value: Node 1-1 ]] added at 0 } Change: { [TreeItem [ value: Node 1-1 ]] added at 0 } Change: { [TreeItem [ value: Node 1-1 ]] added at 0 } Change: { [TreeItem [ value: Node 1-1 ]] added at 0 } Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException at java.lang.System.arraycopy(Native Method) at javafx.collections.transformation.FilteredList.addRemove(FilteredList.java:269) at javafx.collections.transformation.FilteredList.sourceChanged(FilteredList.java:144) at javafx.collections.transformation.TransformationList.lambda$getListener$15(TransformationList.java:106) at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88) at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:164) at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73) at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:75) at javafx.scene.control.TreeTableView$TreeTableViewArrayListSelectionModel.handleSelectedCellsListChangeEvent(TreeTableView.java:3312) at javafx.scene.control.TreeTableView$TreeTableViewArrayListSelectionModel.lambda$new$125(TreeTableView.java:2313) at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:164) 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 javafx.collections.transformation.SortedList.sourceChanged(SortedList.java:108) at javafx.collections.transformation.TransformationList.lambda$getListener$15(TransformationList.java:106) at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88) at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:164) 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 javafx.collections.ModifiableObservableListBase.addAll(ModifiableObservableListBase.java:102) at com.sun.javafx.scene.control.SelectedCellsMap.addAll(SelectedCellsMap.java:146) at javafx.scene.control.TreeTableView$TreeTableViewArrayListSelectionModel.selectIndices(TreeTableView.java:2832) at javafx.scene.control.MultipleSelectionModel.selectRange(MultipleSelectionModel.java:176) at TreeTableViewSample.selectChildrenOfRows(TreeTableViewSample.java:96) at TreeTableViewSample.lambda$start$1(TreeTableViewSample.java:64) at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:361) 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:147) at javafx.scene.control.TreeTableView.setExpandedItemCount(TreeTableView.java:1088) at javafx.scene.control.TreeTableView.updateExpandedItemCount(TreeTableView.java:1861) at javafx.scene.control.TreeTableView.getExpandedItemCount(TreeTableView.java:1092) at com.sun.javafx.scene.control.behavior.TreeTableCellBehavior.getItemCount(TreeTableCellBehavior.java:72) at com.sun.javafx.scene.control.behavior.TableCellBehaviorBase.doSelect(TableCellBehaviorBase.java:110) at com.sun.javafx.scene.control.behavior.CellBehaviorBase.mouseReleased(CellBehaviorBase.java:159) at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96) at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89) at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) at javafx.event.Event.fireEvent(Event.java:198) at javafx.scene.Scene$MouseHandler.process(Scene.java:3757) at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485) at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762) at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:388) at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387) at com.sun.glass.ui.View.handleMouseEvent(View.java:555) at com.sun.glass.ui.View.notifyMouse(View.java:937) at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139) at java.lang.Thread.run(Thread.java:745) REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import java.util.*; import javafx.application.Application; import javafx.collections.*; import javafx.collections.transformation.*; import javafx.beans.property.ReadOnlyStringWrapper; import javafx.scene.*; import javafx.scene.control.*; import javafx.scene.control.TreeTableColumn.CellDataFeatures; import javafx.stage.Stage; public class TreeTableViewSample extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) { final TreeItem<String> childNode1 = new TreeItem<>("Child Node 1"); childNode1.getChildren().addAll( new TreeItem<String>("Node 1-1"), new TreeItem<String>("Node 1-2") ); final TreeItem<String> root = new TreeItem<>("Root node"); root.setExpanded(true); root.getChildren().add(childNode1); TreeTableColumn<String,String> column = new TreeTableColumn<>("Column"); column.setPrefWidth(190); column.setCellValueFactory((CellDataFeatures<String, String> p) -> new ReadOnlyStringWrapper(p.getValue().getValue())); final TreeTableView<String> treeTableView = new TreeTableView<>(root); treeTableView.getColumns().add(column); treeTableView.setPrefWidth(200); treeTableView.setShowRoot(true); treeTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); // Select all children of expanded node. treeTableView.expandedItemCountProperty().addListener((observable, oldCount, newCount) -> { if (newCount.intValue() > oldCount.intValue()) { selectChildrenOfRows(treeTableView, treeTableView.getSelectionModel().getSelectedIndices()); } }); filteredList = treeTableView.getSelectionModel().getSelectedItems().filtered(Objects::nonNull); filteredList.addListener((ListChangeListener.Change<? extends TreeItem<String>> change) -> { System.out.printf("Change: %s\n", change); }); final Scene scene = new Scene(new Group(), 200, 400); Group sceneRoot = (Group)scene.getRoot(); sceneRoot.getChildren().add(treeTableView); stage.setTitle("Tree Table View Samples"); stage.setScene(scene); stage.show(); } private FilteredList<TreeItem<String>> filteredList; private void selectChildrenOfRows(TreeTableView<String> table, Collection<Integer> selectedRows) { for (int index: selectedRows) { TreeItem<String> item = table.getTreeItem(index); if (item != null && item.isExpanded() && !item.getChildren().isEmpty()) { int startIndex = index + 1; int maxCount = startIndex + item.getChildren().size(); table.getSelectionModel().selectRange(startIndex, maxCount); } } } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : Don't create a FilteredList from the selectedItems property of a TreeTableView.
|