3

I think I perhaps have found a bug in Java, or maybe I am doing something wrong.

I populate a container based on some received data. The container has one or more ComboBoxes. On ComboBox selection change I receive new data. I then clear the GridPane and re-add the nodes (that still exist in the new data, and/or add new nodes).

The ComboBox still has focus, but I am unable to activate it again on click. Anything which causes the ComboBox to lose focus (such as focusing another component) will cause it to work again.

This is an simplified example. Tried with jdk1.8.0_162 and jdk-9.0.4

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ComboBoxTest extends Application {

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

    @Override
    public void start(Stage stage) {
        VBox root = new VBox();

        final ComboBox<String> choices = new ComboBox<>();
        choices.getItems().add("Test1");
        choices.getItems().add("Test2");
        root.getChildren().add(choices);

        choices.getSelectionModel().selectedItemProperty().addListener(
            (observable, oldValue, newValue) -> {
                root.getChildren().clear();
                root.getChildren().add(choices);
        });

        Platform.setImplicitExit(true);
        stage.setScene(new Scene(root));
        stage.show();
    }
}

The design is dynamic. I have a list of values received from a server. This is used to create and place ComboBox on a grid. When the user changes a selection in a ComboBox it receive a new list of values from the server. This list may still contain values that corresponds to existing nodes in the grid. They are reused rather than re-created.

DJViking
  • 732
  • 1
  • 9
  • 23
  • why did you change the example? please don't post questions like moving bullets .. you get our time for free so please make it as easy as possible to follow (or lead ) – kleopatra Jan 31 '18 at 11:05
  • @Michael generally edits shouldn't touch code except for minor changes like formating or fixing typos ;) But I agree with you: your example was strictly to the point and let sillyfly (in a comment to the answer that's now deleted) correctly guess the the underlying reason – kleopatra Jan 31 '18 at 11:08
  • I changed the example because it was wrong. It was an earlier example. I needed to demonstrate an example with two checkboxes. Edit: So you changed my example. Why, I thought I had posted a wrong one. – DJViking Jan 31 '18 at 11:11
  • The second ComboBox was added to illustrate that that one works, while the first is locked. If you edit someone elses example add a comment on it... – DJViking Jan 31 '18 at 11:13
  • 1
    @Michael used your minimal example in the answer, thanks :) At OP: having a second combo or not or changing the items along with the removal/readding is irrelevant IMO – kleopatra Jan 31 '18 at 11:28

1 Answers1

2

Just to not loose reason and solution posted as comment to the deleted answer by sillyfly (post your own and I'll delete this :)

A little guess as to the underlying cause/issue - the change causes the ComboBox to disappear while its list (which is technically a different stage) is showing. My guess is that leaves it in an indefinite state where it thinks the list is still showing, but it never hides so it doesn't reset. In this case, maybe calling ComboBox::hide will also work

This assumption is correct as you can see if you change the selection by keyboard (in which case the dropdown is not open): the combo is still accessible by keyboard and mouse. So hiding the dropdown before removing indeed is the solution.

In code (the simplified example in the Michael's edit)

public class ReaddFocusedCombo extends Application {

    @Override
    public void start(Stage stage) {
        VBox root = new VBox();

        final ComboBox<String> choices = new ComboBox<>();
        choices.getItems().add("Test1");
        choices.getItems().add("Test2");
        root.getChildren().add(choices);

        choices.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            // guess by sillyfly: combo gets confused if popup still open 
            choices.hide();
            root.getChildren().clear();
            root.getChildren().add(choices);
            // suggested in answer: working but then the choice isn't focused
            //root.requestFocus();
            // doesn't work
            //  choices.requestFocus();
        });

        stage.setScene(new Scene(root));
        stage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }

}

Update: a little search in the bug parade turned up a similar misbehaviour on adding a showing combo which was fixed on initial attaching to a scene, but missed the dynamic use case. Filed a new issue for the latter.

kleopatra
  • 49,346
  • 26
  • 88
  • 189