1

I have a TextField embedded in an AnchorPane along with a couple of buttons. The TextField does not have focus by default, because I want it to show the prompt text (see prompttext in textfield of javafx 2 hides on focus after some java 7 update - this appears to be a known issue). I want the TextField to receive focus when the user presses any key other than ENTER or ESCAPE. I've created an EventHandler that is attached to my AnchorPane.setOnKeyPressed() (and to the buttons' onKeyPressed listeners) which runs a switch on the keyboard event and defaults to:

                    default:
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            myTxt.requestFocus();
                            myTxt.fireEvent(event);
                        }
                    });

This does send the focus to the TextField; however, the key that I've pressed does not actually show up in the TextField. In other words, if I type

test

the TextField will receive the focus, but only

est

shows up in the field. I've added logging to my KeyEvent listener for both the anchorpane/buttons and to the TextField, which shows me:

Oct 29, 2013 2:22:11 PM com.myapp.AppMainController$4 handle
INFO: Got key t at source Button[id=myBtn, styleClass=button]
Oct 29, 2013 2:22:11 PM com.myapp.AppMainController$6 handle
INFO: Got key t at source TextField[id=myTxt, styleClass=text-input text-field]

So the key event is getting to the TextField, however, it never shows up in the box. If I continue to type, the remaining text does show up, and if I gain focus by typing a combination like SHIFT-T for a capital T, it will show up (it seems that the shift keypress is the one that is "lost" instead of the letter itself).

Has anyone else encountered this? Is this a bug in JavaFX2 or am I doing something wrong? I'm using Java 7u45 with its included JavaFX 2.2.45, for reference.

Edit 1: I should clarify that this happens on switching focus to the TextField regardless of whether the focus was switched from the pane or a button.

Edit 2 (Solution): The actual problem was the "Platform.runLater" wrapper. If I simply request focus without the "runLater", my key events show up as I expect.

                    default:
                        myTxt.requestFocus();
Community
  • 1
  • 1
Nate Simpson
  • 118
  • 1
  • 10
  • 1
    I assume your Event is consumed by activating the Focus. You need to relay it further and consume it there. – thatsIch Oct 30 '13 at 17:32
  • That's my assumption as well, but the problem is that it results in inconsistent behavior from a user perspective because you get different behavior with "t" vs. "T" because the shift keypress is counted as a separate event. What I was hoping is that I'm missing some obvious way to prevent the event from being consumed "on focus" because that isn't documented anywhere as far as I can tell so it just comes across as buggy behavior. It can be worked around with `if (!event.isShiftDown()) {myTxt.appendText(event.getText());}` in the runLater after the focus request, but it feels messy. – Nate Simpson Oct 30 '13 at 19:07

1 Answers1

1

I am not sure how your context looks like but I solved it like this

public class Main extends Application {
    @Override
    public void start(Stage stage) {        
        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));

        final TextField textField = new TextField();
        final Button button = new Button();

        vbox.getChildren().addAll(textField, button);


        vbox.onKeyPressedProperty().set(new EventHandler<KeyEvent>() {
            @Override public void handle(KeyEvent event) {
                textField.requestFocus();
            }
        });

        stage.setScene(new Scene(vbox, 300, 500));
        stage.show();
    }

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

the important part would be

vbox.onKeyPressedProperty().set(new EventHandler<KeyEvent>() {
    @Override public void handle(KeyEvent event) {
        textField.requestFocus();
    }
});

By using the keyPressedProperty, it will already activate when you press the any button and not when you type/release it. Works with capitals and non-capitals.

Edit

The button is inserted to be able to "test" non-focus of the TextField by clicking it you can give it the focus.

Edit 2

to match the actual answer, you use some workaround using Platform.runLater which you actually need in multiple cases. This is a code inside an IntegerField (extends TextField) so I am its own methods.

this.setOnMouseClicked(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent paramT) {
        Platform.runLater(new Runnable() {
            @Override public void run() {
                if (isFocused() && !getText().isEmpty()) {
                    selectAll();
                }               
            }
        });
    }
});
thatsIch
  • 828
  • 11
  • 23
  • I'll accept your answer because it led me to the correct answer, which is that if you wrap the EventHandler textField.requestFocus() in a Platform.runLater(), the first keypress is eaten. I'd still like to know why this is, but at least it seems to be solved. Thanks.:) – Nate Simpson Oct 31 '13 at 21:52
  • Funny Fact: I just used this "work-around" myself in some other context while creating a IntegerField (extends TextField). I can edit my answer to match the "solution" – thatsIch Oct 31 '13 at 22:51
  • Btw you should edit your main post with the actual solution what worked for you (as in code) – thatsIch Oct 31 '13 at 22:54
  • Edited as you suggested - but yes, I do use runLater in other cases. I think technically, runLater should only be used when you are trying to adjust something on the application thread from another thread (though my understanding of JavaFX is still at the beginner level), however, and that's why it wasn't working for me - I used a RunLater from the application thread itself, so it ate the event I was currently dealing with on that thread. – Nate Simpson Oct 31 '13 at 23:53
  • Yes I think it is a bug on JavaFX 2.2 part. Not sure though if its fixed in the J8 branch already. I saw some other post on SO which suggested this "method" and they said too its probably a bug. – thatsIch Nov 01 '13 at 11:44