Issue
I am writing a simpe login GUI that is composed by a GridPane, which is the main container, then a TextField which takes in the user nickname and finally a login Button.
I wrote the GUI structure in FXML combined with CSS.
What I wanted to do was keeping the login Button disabled until the user actually wrote something in the TextField. I could only find an answer related to this but I wanted to know what was the best method to put this Listener in the FXML code itself so that I could get a cleaner code in the FXML controller.
I tried to use the method onKeyTyped but that didn't do the work cause I get no response whenever I'm typing in the TextField.
This is my FXML code
<TextField fx:id="usernameTextField"
promptText="Username"
onKeyTyped="#userTyped"
stylesheets="@loginStyle.css">
What's the best method to achieve this?
Solution
In general, if you want to perform an action if the text of a text field changes, you need to register a listener with the text field's textProperty()
, which you haver to do in the controller:
@FXML
private TextField usernameTextField ;
public void initialize() {
usernameTextField.textProperty().addListener((obs, oldText, newText) -> {
// do what you need with newText here, e.g.
loginButton.setDisable(newText.isEmpty());
});
}
However, if all you need is to bind a property in one control to a property in another control (or some simple dependency of that property), you can use FXML expression binding:
<TextField fx:id="usernameTextField"/>
<Button text="Login" disable="${usernameTextField.text.empty}" />
Here's a SSCCE:
ButtonDisableTest.fxml
:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.Button?>
<VBox alignment="CENTER" spacing="5" xmlns:fx="http://javafx.com/fxml/1">
<TextField fx:id="usernameTextField"/>
<Button text="Login" disable="${usernameTextField.text.empty}" />
</VBox>
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class ButtonDisableTest extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("ButtonDisableTest.fxml"));
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Answered By - James_D
Answer Checked By - Willingham (JavaFixing Volunteer)