2017-02-06 3 views
1

J'essaye de faire un contrôle personnalisé dans JavaFX en utilisant une fonction de liaison. C'est mon problème: j'ai une classe avec un DoubleProperty que j'utilise pour calculer la position d'un élément dans mon contrôle personnalisé. Voici le code:La méthode invalidate() JavaFX Property n'est pas appelée avec la liaison

public class CustomControl extends Region { 
    private DoubleProperty positionProperty; 

    public CustomControl() { 
    positionProperty= new DoublePropertyBase(0.0) { 
     @Override public Object getBean() { return CustomControl.this; } 
     @Override public String getName() { return "position"; } 
     @Override protected void invalidated() { updatePostion(); } 
    }; 
    } 

    public DoubleProperty positionProperty() { return positionProperty; } 
    public double getPosition() { return positionProperty.get(); } 
    public void setPosition(double value) { positionProperty.set(value); } 

    private void updatePosition() { 
    double value = doubleProperty.get(); 
    //compute the new position using value 
    } 
} 

Dans ma demande j'ai deux CustomControl s et je veux que quand je l'appelle la méthode setPosition() le premier d'entre eux, la seconde met à jour la position de son composant ainsi. Pour ce faire, je binded le positionProperty des deux CustomControl s comme ceci:

CustomControl control1 = new CustomControl(); 
CustomControl control2 = new CustomControl(); 
control2.positionProperty.bind(control1.positionProperty); 

Puis quand je l'appelle par exemple

control1.setPosition(50.0); 

seule la position du composant de control1 est mis à jour, en effet quand je l'appelle la méthode setPosition(), la méthode invalidated() du positionProperty de control1 est effectivement appelée, mais pas celle du positionProperty de contol2 comme je l'ai espéré. Comment dois-je réaliser ce que je veux? Je vous remercie!

PS: Je remarque aussi que la méthode bindBidirectional() au lieu de bind() œuvres, mais il ne devrait pas fonctionner en utilisant uniquement bind() aussi?

EDIT: exemple de code est disponible ici: https://[email protected]/luca_bertolini/customcontrolexample.git

+0

Quelle que soit la raison pour laquelle vous créez une implémentation de classe anonyme de 'DoubleProperty'? Votre problème provient probablement de votre substitution de la méthode 'invalidated', sans appeler la méthode de base (' super'). – Itai

+0

@sillyfly J'ai créé une classe anonyme car j'ai besoin de beaucoup de ces 'CustomControl' sur l'écran et l'utilisation d'une classe anonyme au lieu de définir un écouteur sur la propriété réduira l'utilisation de la mémoire et la complexité informatique. De même, l'implémentation par défaut de 'invalidate()' est vide donc ça ne change pas beaucoup si j'appelle 'super.invalidate()' ou non. –

+0

Poster un [MCVE]. J'ai testé ceci et cela a fonctionné exactement comme prévu ('System.out.println (control2.getPosition());' affiché '50.0'). Il doit y avoir une erreur ailleurs dans le code que vous n'avez pas posté. –

Répondre

1

JavaFX utilise l'évaluation paresseuse pour toutes les liaisons, ce qui signifie que lorsqu'un changement se produit sur votre objet out.positionProperty, la nouvelle valeur n'est pas immédiatement prise en compte. Cela arrive plus tard, si et seulement si la valeur est demandée ultérieurement.

Essayez ceci:

out.positionProperty().addListener(new InvalidationListener() { 
    @Override 
    public void invalidated(final Observable observable) { 
     // System.out.println("It must go now."); 
    } 
}); 

et vous verrez que cette fois votre code fonctionne comme vous le souhaitez.

+0

Oui, cela fonctionne. Je suppose que c'est la seule façon de réaliser ce que je veux. Je vous remercie! –

+0

Vous êtes les bienvenus .. – Meziane