ADDITIONAL SYSTEM INFORMATION :
Microsoft Windows [Version 10.0.18363.1198]
openjdk version "11.0.5" 2019-10-15
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.5+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.5+10, mixed mode)
A DESCRIPTION OF THE PROBLEM :
Exception on sorting after replacing all children with first cell selected.
Issue is only replicable while having selected first cell/row.
Issue is replicable on SINGLE and MULTIPLE selection modes.
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: [ fromIndex: 0, toIndex: 1, size: 0 ]
at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.subList(ReadOnlyUnbackedObservableList.java:171)
at javafx.collections.ListChangeListener$Change.getAddedSubList(ListChangeListener.java:243)
at com.sun.javafx.scene.control.SelectedItemsReadOnlyObservableList.getAddedElements(SelectedItemsReadOnlyObservableList.java:156)
at com.sun.javafx.scene.control.SelectedItemsReadOnlyObservableList.lambda$new$1(SelectedItemsReadOnlyObservableList.java:65)
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.scene.control.ReadOnlyUnbackedObservableList._endChange(ReadOnlyUnbackedObservableList.java:64)
at javafx.scene.control.MultipleSelectionModelBase$SelectedIndicesList._endChange(MultipleSelectionModelBase.java:896)
at javafx.scene.control.ControlUtils.updateSelectedIndices(ControlUtils.java:202)
at javafx.scene.control.TreeTableView$TreeTableViewArrayListSelectionModel.fireCustomSelectedCellsListChangeEvent(TreeTableView.java:3354)
at javafx.scene.control.TreeTableView$TreeTableViewArrayListSelectionModel.access$2100(TreeTableView.java:2390)
at javafx.scene.control.TreeTableView.sort(TreeTableView.java:1899)
at javafx.scene.control.TreeTableView.doSort(TreeTableView.java:1940)
at javafx.scene.control.TreeTableView.lambda$new$0(TreeTableView.java:392)
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 javafx.collections.ModifiableObservableListBase.setAll(ModifiableObservableListBase.java:90)
at javafx.collections.ObservableListBase.setAll(ObservableListBase.java:251)
at javafx.scene.control.skin.TableColumnHeader.sortColumn(TableColumnHeader.java:883)
at javafx.scene.control.skin.TableColumnHeader.lambda$static$14(TableColumnHeader.java:271)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
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.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:3854)
at javafx.scene.Scene$MouseHandler.access$1200(Scene.java:3582)
at javafx.scene.Scene.processMouseEvent(Scene.java:1852)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2591)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:391)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433)
at com.sun.glass.ui.View.handleMouseEvent(View.java:556)
at com.sun.glass.ui.View.notifyMouse(View.java:942)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:834)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run provided code sample application.
2. Select first cell in first row using mouse.
3. Press "Reset children" button in bottom side of window.
4. Click on first column ("Column_0") to toggle sorting.
5. Select first cell in first row using mouse.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
no exception is thrown and After 5. first cell is selected.
ACTUAL -
After 4.
"Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: [ fromIndex: 0, toIndex: 1, size: 0 ]" is thrown
After 5.
"Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: bitIndex < 0: -1" is thrown
---------- BEGIN SOURCE ----------
package com.example;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TreeTableViewSelectionIssue
{
public static void main( String[] args )
{
System.err.println( Runtime.version().toString() );
Application.launch( MainFx.class, args );
}
public static class MainFx extends Application
{
@Override
public void start( final Stage primaryStage ) throws Exception
{
System.err.println( System.getProperty( "javafx.version" ) );
final List< Map< String, String > > data = createData( 5 );
final TreeTableView< Map< String, String > > tableView = createTableView( data );
fillTableData( tableView, data );
VBox.setVgrow( tableView, Priority.ALWAYS );
final ScrollPane sp = new ScrollPane( tableView );
sp.setFitToWidth( true );
sp.setFitToHeight( true );
final Button button = new Button( "Reset children" );
button.setOnAction( aActionEvent -> {
final List< Map< String, String > > generatedData = createData( 5 );
final List< TreeItem< Map< String, String > > > newChildren =
generatedData.stream().map( TreeItem::new ).collect( Collectors.toList() );
final TreeItem< Map< String, String > > root = tableView.getRoot();
final ObservableList< TreeItem< Map< String, String > > > children = root.getChildren();
children.clear();
// tableView.getSelectionModel().clearSelection();
children.addAll( newChildren );
} );
final VBox parent = new VBox( sp, button );
final Scene aScene = new Scene( parent, 800, 600 );
primaryStage.setScene( aScene );
primaryStage.show();
}
private void fillTableData( final TreeTableView< Map< String, String > > aTableView,
final List< Map< String, String > > aData )
{
final TreeItem< Map< String, String > > root = new TreeItem<>();
root.getChildren().setAll( aData.stream().map( TreeItem::new ).collect( Collectors.toList() ) );
aTableView.setShowRoot( false );
aTableView.setRoot( root );
}
private TreeTableView< Map< String, String > > createTableView(
final List< Map< String, String > > aData )
{
final TreeTableView< Map< String, String > > table = new TreeTableView<>();
final Map< String, String > firstRow = aData.get( 0 );
final List< TreeTableColumn< Map< String, String >, String > > columns =
firstRow.keySet().stream().map( text -> {
final TreeTableColumn< Map< String, String >, String > column =
new TreeTableColumn<>( text );
column.setCellValueFactory( param -> {
final TreeItem< Map< String, String > > v = param.getValue();
final Map< String, String > map = v.getValue();
return new ReadOnlyStringWrapper( map.get( text ) );
} );
return column;
} ).collect( Collectors.toList() );
table.getColumns().addAll( columns );
table.setMaxWidth( Double.MAX_VALUE );
table.setMaxHeight( Double.MAX_VALUE );
table.getSelectionModel().setCellSelectionEnabled( true );
table.getSelectionModel().setSelectionMode( SelectionMode.SINGLE );
return table;
}
private List< Map< String, String > > createData( final int rowNumber )
{
final int colNumber = 12;
final List< Map< String, String > > data = new ArrayList<>( rowNumber );
for( int i = 0; i < rowNumber; i++ )
{
final Map< String, String > row = new LinkedHashMap<>( colNumber );
for( int k = 0; k < colNumber; k++ )
{
row.put( "Column_" + k,
"Value " + UUID.randomUUID().toString().substring( (int)( Math.random() * 20d ) ) );
}
data.add( row );
}
return data;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Uncomment
// tableView.getSelectionModel().clearSelection();
in provided source code for test case
FREQUENCY : always
Microsoft Windows [Version 10.0.18363.1198]
openjdk version "11.0.5" 2019-10-15
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.5+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.5+10, mixed mode)
A DESCRIPTION OF THE PROBLEM :
Exception on sorting after replacing all children with first cell selected.
Issue is only replicable while having selected first cell/row.
Issue is replicable on SINGLE and MULTIPLE selection modes.
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: [ fromIndex: 0, toIndex: 1, size: 0 ]
at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.subList(ReadOnlyUnbackedObservableList.java:171)
at javafx.collections.ListChangeListener$Change.getAddedSubList(ListChangeListener.java:243)
at com.sun.javafx.scene.control.SelectedItemsReadOnlyObservableList.getAddedElements(SelectedItemsReadOnlyObservableList.java:156)
at com.sun.javafx.scene.control.SelectedItemsReadOnlyObservableList.lambda$new$1(SelectedItemsReadOnlyObservableList.java:65)
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.scene.control.ReadOnlyUnbackedObservableList._endChange(ReadOnlyUnbackedObservableList.java:64)
at javafx.scene.control.MultipleSelectionModelBase$SelectedIndicesList._endChange(MultipleSelectionModelBase.java:896)
at javafx.scene.control.ControlUtils.updateSelectedIndices(ControlUtils.java:202)
at javafx.scene.control.TreeTableView$TreeTableViewArrayListSelectionModel.fireCustomSelectedCellsListChangeEvent(TreeTableView.java:3354)
at javafx.scene.control.TreeTableView$TreeTableViewArrayListSelectionModel.access$2100(TreeTableView.java:2390)
at javafx.scene.control.TreeTableView.sort(TreeTableView.java:1899)
at javafx.scene.control.TreeTableView.doSort(TreeTableView.java:1940)
at javafx.scene.control.TreeTableView.lambda$new$0(TreeTableView.java:392)
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 javafx.collections.ModifiableObservableListBase.setAll(ModifiableObservableListBase.java:90)
at javafx.collections.ObservableListBase.setAll(ObservableListBase.java:251)
at javafx.scene.control.skin.TableColumnHeader.sortColumn(TableColumnHeader.java:883)
at javafx.scene.control.skin.TableColumnHeader.lambda$static$14(TableColumnHeader.java:271)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
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.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:3854)
at javafx.scene.Scene$MouseHandler.access$1200(Scene.java:3582)
at javafx.scene.Scene.processMouseEvent(Scene.java:1852)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2591)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:391)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433)
at com.sun.glass.ui.View.handleMouseEvent(View.java:556)
at com.sun.glass.ui.View.notifyMouse(View.java:942)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:834)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run provided code sample application.
2. Select first cell in first row using mouse.
3. Press "Reset children" button in bottom side of window.
4. Click on first column ("Column_0") to toggle sorting.
5. Select first cell in first row using mouse.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
no exception is thrown and After 5. first cell is selected.
ACTUAL -
After 4.
"Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: [ fromIndex: 0, toIndex: 1, size: 0 ]" is thrown
After 5.
"Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: bitIndex < 0: -1" is thrown
---------- BEGIN SOURCE ----------
package com.example;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TreeTableViewSelectionIssue
{
public static void main( String[] args )
{
System.err.println( Runtime.version().toString() );
Application.launch( MainFx.class, args );
}
public static class MainFx extends Application
{
@Override
public void start( final Stage primaryStage ) throws Exception
{
System.err.println( System.getProperty( "javafx.version" ) );
final List< Map< String, String > > data = createData( 5 );
final TreeTableView< Map< String, String > > tableView = createTableView( data );
fillTableData( tableView, data );
VBox.setVgrow( tableView, Priority.ALWAYS );
final ScrollPane sp = new ScrollPane( tableView );
sp.setFitToWidth( true );
sp.setFitToHeight( true );
final Button button = new Button( "Reset children" );
button.setOnAction( aActionEvent -> {
final List< Map< String, String > > generatedData = createData( 5 );
final List< TreeItem< Map< String, String > > > newChildren =
generatedData.stream().map( TreeItem::new ).collect( Collectors.toList() );
final TreeItem< Map< String, String > > root = tableView.getRoot();
final ObservableList< TreeItem< Map< String, String > > > children = root.getChildren();
children.clear();
// tableView.getSelectionModel().clearSelection();
children.addAll( newChildren );
} );
final VBox parent = new VBox( sp, button );
final Scene aScene = new Scene( parent, 800, 600 );
primaryStage.setScene( aScene );
primaryStage.show();
}
private void fillTableData( final TreeTableView< Map< String, String > > aTableView,
final List< Map< String, String > > aData )
{
final TreeItem< Map< String, String > > root = new TreeItem<>();
root.getChildren().setAll( aData.stream().map( TreeItem::new ).collect( Collectors.toList() ) );
aTableView.setShowRoot( false );
aTableView.setRoot( root );
}
private TreeTableView< Map< String, String > > createTableView(
final List< Map< String, String > > aData )
{
final TreeTableView< Map< String, String > > table = new TreeTableView<>();
final Map< String, String > firstRow = aData.get( 0 );
final List< TreeTableColumn< Map< String, String >, String > > columns =
firstRow.keySet().stream().map( text -> {
final TreeTableColumn< Map< String, String >, String > column =
new TreeTableColumn<>( text );
column.setCellValueFactory( param -> {
final TreeItem< Map< String, String > > v = param.getValue();
final Map< String, String > map = v.getValue();
return new ReadOnlyStringWrapper( map.get( text ) );
} );
return column;
} ).collect( Collectors.toList() );
table.getColumns().addAll( columns );
table.setMaxWidth( Double.MAX_VALUE );
table.setMaxHeight( Double.MAX_VALUE );
table.getSelectionModel().setCellSelectionEnabled( true );
table.getSelectionModel().setSelectionMode( SelectionMode.SINGLE );
return table;
}
private List< Map< String, String > > createData( final int rowNumber )
{
final int colNumber = 12;
final List< Map< String, String > > data = new ArrayList<>( rowNumber );
for( int i = 0; i < rowNumber; i++ )
{
final Map< String, String > row = new LinkedHashMap<>( colNumber );
for( int k = 0; k < colNumber; k++ )
{
row.put( "Column_" + k,
"Value " + UUID.randomUUID().toString().substring( (int)( Math.random() * 20d ) ) );
}
data.add( row );
}
return data;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Uncomment
// tableView.getSelectionModel().clearSelection();
in provided source code for test case
FREQUENCY : always