Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8234247

ComboBox: cancel button must not be triggered if escape is consumed by combo handler

XMLWordPrintable

    • Fix Understood

      To reproduce, run the example below, focus one of the combo, press escape

      expected: message from combo handler printed
      actual: message from cancel button is printed before message from combo handler

      The bug is similar to JDK-8207759 (there reported against ENTER and TextField), with the same underlying reason: ComboBoxBaseBehavior has a keyMapping for ESCAPE which forwards the event to the combo's parent if interpreted as not used. This manual firing of the received keyEvent wrecks the event deliverance sequence such that handlers in the parent hierarchy see the event before the consuming singleton handler of the combo.

      The fix is basically the same: in ComboBoxBaseBehavior, replace the manual forwarding by letting the event travel "naturally" up the chain.

      The example:

      public class ComboCancelButton extends Application {

          private Parent createContent() {
              ObservableList<String> data= FXCollections.observableArrayList("one", "two");
              ComboBox<String> editable = new ComboBox<>(data);
              editable.setEditable(true);
              EventHandler<KeyEvent> consumer = e -> {
                  if (e.getCode() == ESCAPE) {
                      System.out.println("consuming escape");
                      e.consume();
                  }
              };
              editable.setOnKeyPressed(consumer);
              
              ComboBox<String> notEditable = new ComboBox<>(data);
              notEditable.setOnKeyPressed(consumer);
              
              Button cancel = new Button("Cancel");
              cancel.setCancelButton(true);
              cancel.setOnAction(a -> System.out.println("cancel triggered"));
              
              VBox content= new VBox(10, editable, notEditable, cancel);
              return content;
          }

          @Override
          public void start(Stage stage) throws Exception {
              stage.setScene(new Scene(createContent()));
              stage.show();
          }

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

      }

            fastegal Jeanette Winzenburg
            fastegal Jeanette Winzenburg
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: