There is a JavaFX project. The interface is described in an FXML file containing a TextField object:

<TextField fx:id="field" layoutX="95.0" layoutY="40.0" prefHeight="25.0" prefWidth="35.0" /> 

You must handle the text change event in the field. I saw how this is done if TextField was created in java code, but how to do it when described in FXML is not clear. The attribute "onInputMethodTextChanged" added to the TextField tag:

 onInputMethodTextChanged="#controller_method_name" 

But, for some reason, the method is not called when entering text into the field (there are no errors). I would like to do this, if possible, through some indication of the handler method in FXML right away (as with "onInputMethodTextChanged" I tried).

  • one
    try using one of the methods: onKeyPressed, onKeyReleased, onKeyTyped - Victor

1 answer 1

Apparently, what you want in the java-code of the controller would look like:

 field.textProperty().addListener((observable, oldValue, newValue)->{...}); 

For JavaFX 8+:

Especially for your case (for the ChangeListener properties handler) in JavaFX 8 you made changes that allow you to write like this:

 <TextField onTextChange="#method" /> 

In this case, the method should have the following signature in the controller:

 public void method(ObservableValue observable, String oldValue, String newValue) { System.out.println("textonchange2(): "+oldValue+" -> "+newValue); } 

Reference to the documentation:

JavaFX 8. Introduction to FXML: Special handlers for collections and properties


The following is true for JavaFX 2. *:

(I leave as an example how to use javascript in FXML)

Unfortunately, the standard TextField does not have a property to do something like <TextField onTextChange="#..."/> .

Also, the type of the textProperty property is TextProperty , and there is no suitable JavaFX property in this class either (to try something like <TextField><text onChange="#..."/></TextField> .

It remains to either implement your own descendant class TextField , in which you implement the necessary functionality, or use some other workaround.

Of the workarounds, the least difficult, in my opinion, is the use of the Nashorn embedded javascript engine:

// changetext.fxml:

 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?language javascript?> <VBox xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="changetext.ChangetextController" prefHeight="400.0" prefWidth="600.0"> <TextField fx:id="myTextField" text="Привет!"/> <fx:script> myTextField.textProperty()["addListener(javafx.beans.value.ChangeListener)"]( function(observable, oldValue, newValue){ print('observable: ' + observable); print(' oldValue: ' + oldValue); print(' newValue: ' + newValue); controller.js2controller(observable, oldValue, newValue); }); </fx:script> </VBox> 

For this example, it is important that the script is after the element — in this case, the object myTextField has already been created by FXMLLoader .

You should also pay attention to specifying the signature when calling the addListener() method, since It has another overloaded version with an InvalidationListener .

Java controller methods are called from javascript via the controller object, which is added to the global javascript namespace FXMLLoader when parsing the fx:controller attribute.

Related controller files and applications:

// ChangetextController.java:

 package changetext; import javafx.beans.value.ObservableValue; import javafx.scene.control.TextField; public class ChangetextController { public TextField myTextField; public void js2controller(ObservableValue observable, String oldValue, String newValue) { System.out.println("js2controller(): " + oldValue + " -> " + newValue); } } 

// ChangeTextMain.java:

 package changetext; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; public class ChangeTextMain extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) throws Exception { Parent root = FXMLLoader.load(getClass().getResource("changetext.fxml")); primaryStage.setScene(new Scene(root)); primaryStage.show(); } }