Activation / suppression d'un bindBidirectionnal() via un listener
Bonjour,
Je cherche à activer et supprimer le binding bidirectionnel entre un champ de saisie TextField et une propriété (DoubleProperty) en fonction de l'élément que l'utilisateur sélectionne dans une liste.
L'idée est de pouvoir apporter des modifications à la variable directement depuis la Texfield, mais cette variable peut également être mise à jour par ailleurs dans le programme, d'où l'utilisation d'un binding bidirectionnel.
J'ai besoin que ce binding se mette en place via un listener. J'ai donc reproduit un exemple simplifié qui reproduit le comportement rencontré.
Je rencontre le problème suivant :
Lorsque le binding est défini en dehors d'un listener (option 1), le code fonctionne correctement : on peut apporter des modifications directement dans le champ de saisie Texfield, ou via le bouton qui incrémente la valeur stockée dans cette variable.
La second test (option 2) réalisé consiste à utiliser une checkbox pour installer ou supprimer ce binding via un changelistener (bindingCheckChange). A ce moment là, les modifications apportées à la variable ne sont pas transmises au champ de saisie TextField et inversement. Ce sont pourtant les mêmes commandes qui sont utilisées pour installer le binding.
Je ne parviens pas à m'expliquer ce comportement, ni à régler ce problème.
Merci d'avance pour votre aide.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
|
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.util.StringConverter;
import javafx.util.converter.NumberStringConverter;
import javafx.stage.Stage;
public class HelloFX extends Application {
private DoubleProperty aProperty = new SimpleDoubleProperty(2.5);
private final TextField numberField = new TextField();
private Button button = new Button("+1");
private final StringConverter<Number> converter = new NumberStringConverter();
@Override
public void start(Stage stage) {
CheckBox checkBox = new CheckBox("BidirectionalBinding");
VBox vbox = new VBox (checkBox, numberField, button);
vbox.setSpacing(5);
/* Le bouton permet d'incrémenter la valeur stockée dans la variable aProperty */
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
aProperty.set(aProperty.get()+1.0);
}
});
/* Déclaration et mise en place d'un listener permettant d'activer ou de supprimer le binding bindBidirectionnal() */
ChangeListener bindingCheckChange = new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> ov,
Boolean old_val, Boolean new_val) {
if (new_val)
System.out.println("checkbox activated => isntallation bindBidirectionnal");
numberField.textProperty().bindBidirectional(aProperty, converter);
// Bindings.bindBidirectional(numberField.textProperty(), aProperty, converter);
if (!new_val)
System.out.println("checkbox unchecked => unbindBidirectional");
numberField.textProperty().unbindBidirectional(aProperty);
}};
checkBox.selectedProperty().addListener(bindingCheckChange);
/* Listener permettant de suivre les changements apportés Ã* la variable 'aProperty' */
aProperty.addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
System.out.println("aProperty changed : "+ oldValue+ " --> "+ newValue);
}
});
/* Option 1 : Installation du binding directement en utilisant l'une ou l'autre des deux commandes suivantes => cela fonctionne correctement */
//Bindings.bindBidirectional(numberField.textProperty(), aProperty, converter);
//numberField.textProperty().bindBidirectional(aProperty, converter);
/* Option 2: Test des fonctions de binding en passant par le une checkbox => Cela ne fonctionne pas*/
checkBox.selectedProperty().set(true);
Scene scene = new Scene(vbox, 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
} |