Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CheckComboBox: IndexOutOfBoundsException on clearChecks() #1531

Closed
dsubelman opened this issue Nov 20, 2023 · 6 comments
Closed

CheckComboBox: IndexOutOfBoundsException on clearChecks() #1531

dsubelman opened this issue Nov 20, 2023 · 6 comments

Comments

@dsubelman
Copy link

dsubelman commented Nov 20, 2023

A bug was introduced in v11.2.0 where an IndexOutOfBoundsException is thrown when calling comboBox.getCheckModel().clearChecks() after an item is removed.

Here's an example that reproduces the issue:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import org.controlsfx.control.CheckComboBox;

public class Test extends Application {
    
    @Override
    public void start(Stage stage) throws Exception {
            
        CheckComboBox<String> cb = new CheckComboBox<>();
        cb.getItems().setAll("James", "Emma", "William");
        
        cb.getCheckModel().checkAll();
        cb.getCheckModel().clearCheck(0);
        cb.getItems().remove(0);
        cb.getCheckModel().clearCheck(0);
        cb.getItems().remove(0);
        cb.getCheckModel().clearChecks();
        cb.getItems().clear();
        
        StackPane root = new StackPane(cb);
        
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
        
    }
    
    public static void main(String[] args) {
        launch();
    }
}

Stack trace:

Exception in thread "JavaFX Application Thread" java.util.NoSuchElementException: java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 1
	at java.base/java.util.AbstractList$Itr.next(AbstractList.java:377)
	at org.controlsfx.control.CheckBitSetModelBase.lambda$new$2(CheckBitSetModelBase.java:116)
	at javafx.base@20.0.2/com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:162)
	at javafx.base@20.0.2/com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:71)
	at javafx.base@20.0.2/javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:238)
	at impl.org.controlsfx.collections.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:44)
	at org.controlsfx.control.CheckBitSetModelBase.lambda$new$1(CheckBitSetModelBase.java:99)
	at javafx.base@20.0.2/com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:162)
	at javafx.base@20.0.2/com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:71)
	at javafx.base@20.0.2/javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:238)
	at impl.org.controlsfx.collections.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:44)
	at org.controlsfx.control.CheckBitSetModelBase.clearChecks(CheckBitSetModelBase.java:205)
	at com.test.Test.start(Test.java:23)
	at javafx.graphics@20.0.2/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:839)
	at javafx.graphics@20.0.2/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:483)
	at javafx.graphics@20.0.2/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at javafx.graphics@20.0.2/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
	at javafx.graphics@20.0.2/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
Caused by: java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 1
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266)
	at java.base/java.util.Objects.checkIndex(Objects.java:359)
	at java.base/java.util.ArrayList.get(ArrayList.java:427)
	at javafx.base@20.0.2/com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:88)
	at org.controlsfx.control.CheckComboBox$CheckComboBoxBitSetCheckModel.getItem(CheckComboBox.java:396)
	at org.controlsfx.control.CheckBitSetModelBase.lambda$new$0(CheckBitSetModelBase.java:87)
	at impl.org.controlsfx.collections.MappingChange$2.get(MappingChange.java:86)
	at java.base/java.util.AbstractList$Itr.next(AbstractList.java:371)
	... 18 more
@dsubelman
Copy link
Author

Is this repo still active?

@danielpeintner
Copy link
Collaborator

Is this repo still active?

I would say yes ;-)
There has been a release published some weeks ago.

I am not the driver behind ControlsFX but I think you (and maybe many others) need to understand that most of the people contributing to an open source project do it in their spare time. If you feel an issue needs to be fixed I think it is a good time to start looking into more closely and help to improve the code 👍.
I am pretty sure a contribution is highly welcome!

@stefanodifrancesco
Copy link

Hello,

I found a more straightforward method to reproduce the bug, which suggests some clues about what might be happening in the code execution:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import org.controlsfx.control.CheckComboBox;

public class Test extends Application {
    
    @Override
    public void start(Stage stage) throws Exception {
            
        CheckComboBox<String> cb = new CheckComboBox<>();
        cb.getItems().setAll("James", "Emma", "William");
        
        StackPane root = new StackPane(cb);
        
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
        
        // Check actions after the stage show. Check on index '2' is vital to reproduce the bug.    
        cb.getCheckModel().check(2);
        cb.getCheckModel().check(1);
        cb.getCheckModel().clearChecks();
        cb.getCheckModel().check(2);

        // It could also be reproduced by checking index '1' instead, as shown below:
        /*
        cb.getCheckModel().check(1);
        cb.getCheckModel().check(0);
        cb.getCheckModel().clearChecks();
        cb.getCheckModel().check(1);
        */

    }
    
    public static void main(String[] args) {
        launch();
    }
}

It is important to note that the checkbox actions are performed after the stage.show() function is called.

Here is the stack trace for reference:

Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: [ fromIndex: -1, toIndex: 0, size: 1 ]
	at impl.org.controlsfx.collections.ReadOnlyUnbackedObservableList.subList(ReadOnlyUnbackedObservableList.java:110)
	at javafx.collections.ListChangeListener$Change.getAddedSubList(ListChangeListener.java:243)
	at org.controlsfx.control.CheckBitSetModelBase.lambda$new$2(CheckBitSetModelBase.java:110)
	at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:162)
	at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:71)
	at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:246)
	at impl.org.controlsfx.collections.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:44)
	at org.controlsfx.control.CheckBitSetModelBase.lambda$new$1(CheckBitSetModelBase.java:99)
	at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:327)
	at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:71)
	at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:246)
	at impl.org.controlsfx.collections.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:44)
	at org.controlsfx.control.CheckBitSetModelBase.check(CheckBitSetModelBase.java:259)
	at it.univaq.disim.ermes.editors.editorQL.main.Test.start(Test.java:28)
	at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:839)
	at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:483)
	at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
	at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)

@credmond
Copy link
Contributor

credmond commented Apr 28, 2024

This is fixed in 11.2.1. Thanks @abhinayagarwal .

@dsubelman
Copy link
Author

I just tested the example shown in the original issue using v11.2.1 and still throws the same IndexOutOfBoundsException.

@credmond , @abhinayagarwal, what was solved in v11.2.1?

@credmond
Copy link
Contributor

credmond commented Apr 30, 2024

@dsubelman Sorry, no, it wasn't solved actually. You're right, the first example is still failing (I was testing the second example -- assumed it was all the same thing).

@abhinayagarwal: can you re-open?

I've not used this control in the past until now, so I can't speak about previous behaviour -- but even since this fix, there are still odd random display bugs, whereby the checkbox of one of the items can stay unchecked permanently (unless you specifically click the checkbox itself). The "title" of the combox doesn't reflect what's visually selected.

It doesn't behave correctly thereafter once this happens, needs to be re-created. Seems to be some listeners gets out of sync, or perhaps something is getting GC'd when it shouldn't.

Just reproduced it now, first time:

image

I can click the label/row of 0 and it'll update the title accordingly, but the checkbox won't change; it'll reamain unselected. This doesn't appear to occur in reverse (checkbox always "checked").

I have typed a lot here now, and realise this should probably be a bug on its own. But really my question is, do we feel these bugs were introduced in 11.2.0?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants