'How to add listeners to bidirectionally bound objects
I am trying to bind a TextArea's textProperty to a StringProperty in controller's initialize() method.
Both of them are listened by listeners to perform some behavior when value changes.
But something weird happens.
I build a simple model to reproduce the situation.
Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setScene(new Scene(root, 400, 300));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
sample.fxml
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.TextArea?>
<GridPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"
prefHeight="300" prefWidth="400">
<TextArea fx:id="textArea"/>
</GridPane>
I don't think the above code is relevant to this question. But just in case, I put it here.
Here is the Controller.
Controller.java
package sample;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
public class Controller {
@FXML
TextArea textArea;
private StringProperty toBind = new SimpleStringProperty();
public void initialize() {
textArea.textProperty().bindBidirectional(toBind);
textArea.textProperty().addListener((observable, oldValue, newValue) -> {
System.out.print("textArea: ");
System.out.println(newValue);
});
toBind.addListener((observable, oldValue, newValue) -> {
System.out.print("toBind: ");
System.out.println(newValue);
});
}
}
With this controller, when I input the sequence 'abcd' to the textarea, I get:
textArea: a
textArea: ab
textArea: abc
textArea: abcd
It seems that the change event for the toBind object is not fired.
So then I tried to print the value of toBind in textArea's Listener.
The new code is:
package sample;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
public class Controller {
@FXML
TextArea textArea;
private StringProperty toBind = new SimpleStringProperty();
public void initialize() {
textArea.textProperty().bindBidirectional(toBind);
textArea.textProperty().addListener((observable, oldValue, newValue) -> {
System.out.print("textArea: ");
System.out.println(newValue);
// ----- New statements. -----
System.out.print("toBind value in textArea: ");
System.out.println(toBind.get());
// ----- New statements. -----
});
toBind.addListener((observable, oldValue, newValue) -> {
System.out.print("toBind: ");
System.out.println(newValue);
});
}
}
Then I got:
toBind: a
textArea: a
toBind value in textArea: a
toBind: ab
textArea: ab
toBind value in textArea: ab
toBind: abc
textArea: abc
toBind value in textArea: abc
toBind: abcd
textArea: abcd
toBind value in textArea: abcd
Why does this happen? The event is fired properly.
Solution 1:[1]
I found 2 solutions to you answer
1:
Declare the StringProperty as static
OR 2:
In the TextArea Listener just call toBind.get()
But honestly I don't know why those work.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | James_D |
