Reputation:
Given
JavaFX App, Input TextField
and Submit Button
There's an EventHandler
attached to the TextField
so that if no text is typed, the Button
should be disabled and vice versa.
Here's my code:
button.setDisable(true); // initially disabled
textField.setOnKeyTyped(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if (textField.getText().trim().isEmpty()) { // if blank textfield
button.setDisable(true);
} else {
button.setDisable(false);
}
}
});
Both Controls are initialized properly. And as far as I know, the difference between KeyTyped and KeyPressed/Released is that Typed is for characters that can actually be typed and shown; whereas Pressed/Released is for any keyboard key including Ctrl, Alt...
Problem
I type into the textField
one character, the button
is still disabled! If I type 2 characters and more and it becomes enabled!
However, when if I do the following:
button.setDisable(true);
textField.setOnKeyReleased(
/*
exact same code as above
*/
);
my problem will be solved.
Question
WHY? Where's the flaw in my code? Why doesn't KeyTyped work as expected?
Upvotes: 2
Views: 2721
Reputation: 21799
The problem is: in the time when you handle the KeyEvent
, it is not sure that the textProperty
of your TextField
was updated or not.
Cleaner and safer approach to add a listener for the textProperty
of the TextField
to be notified when the text of the TextField
changes. Imagine also the usecase that the user pasted some content: in this case there is no KeyEvent
at all, therefore your Button
remains disabled.
Using a listener on textProperty()
button.setDisable(true);
textField.textProperty().addListener((obj, oldVal, newVal) -> {
if (newVal.trim().isEmpty()) { // if blank textfield
button.setDisable(true);
} else {
button.setDisable(false);
}
});
... or even shorter ...
button.setDisable(true);
textField.textProperty().addListener((obj, oldVal, newVal) -> button.setDisable(newVal.trim().isEmpty()));
But, the much cleaner solution to use binding between the disableProperty
of the Button
and the textProperty
of the TextField
.
Using a binding between disableProperty
and textProperty
BooleanBinding textIsEmpty = Bindings.createBooleanBinding(() -> textField.getText().trim().isEmpty(), textField.textProperty());
button.disableProperty().bind(textIsEmpty);
Upvotes: 2