IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

FAQ JavaFXConsultez toutes les FAQ

Nombre d'auteurs : 4, nombre de questions : 507, dernière mise à jour : 2 novembre 2016  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur le forum JavaFX de http://java.developpez.com ainsi que l'expérience personnelle des auteurs.

Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant rédacteur, lisez ceci.

Sur ce, nous vous souhaitons une bonne lecture.

SommairePropriétésBinding de haut niveau (9)
précédent sommaire suivant
 

Pour créer une liaison simple entre deux propriétés de types compatibles, la propriété A et la propriété B, il suffit d'invoquer la méthode bind() de la propriété B en passant en paramètre la propriété A.



Imaginons que nous avons un objet1 disposant de la propriété A et un objet 2 disposant de la propriété B. Établissons une liaison entre A et B, ceci nous donne:

Code Java : Sélectionner tout
objet2.bProperty().bind(objet1.aProperty());

Une fois cette liaison établie et tant qu'elle perdura, il n'est plus possible d'invoquer le setter de la propriété B sans lever d'exception. La valeur de la propriété B sera mise à jour à chaque changement de valeur de la propriété A.

La propriété B ne peut être liée que sur une seule propriété à la fois. Si on établie une liaison entre la propriété B et une autre propriété, C, la liaison avec A est perdue.

Si nous faisons :

Code Java : Sélectionner tout
1
2
objet2.bProperty().bind(objet1.aProperty()); 
objet2.bProperty().bind(objet3.cProperty());

Notre première ligne de code lie B sur A.



Notre seconde ligne de code lie désormais B à C.



On peut avoir autant de propriétés liées sur la propriété A que le besoin s'en fait sentir.

Code Java : Sélectionner tout
1
2
3
objet2.bProperty().bind(objet1.aProperty()); 
objet3.cProperty().bind(objet1.aProperty()); 
objet4.dProperty().bind(objet1.aProperty());

Ici les propriétés B, C et D sont désormais liées à la propriété A, leurs valeurs changeront quand celle de A change. Cependant, les propriétés B, C et D ne sont pas liées entre elles et restent indépendantes l'une de l'autre.



Les liaisons entre propriétés sont établies en utilisant des références et écouteurs faibles, elles n’empêchent donc pas le garbage collector de réclamer des propriétés devenues inaccessibles. Cependant, c'est une bonne pratique que de casser les liaisons devenues inutiles pour éviter des propagations en cascade de propriétés dans votre code ou encore des mises à jour ou affichages incohérents dans votre IU.

Mis à jour le 4 septembre 2014 bouye

Il suffit d'appeler la méthode unbind() de la propriété.

Reprenons notre exemple de la propriété B liée à la propriété A. Si maintenant nous faisons :

Code Java : Sélectionner tout
objet2.bProperty().unbind();

Désormais, les changements de valeur de A ne sont plus répercutés sur la propriété B. Nous pouvons également invoquer les setters de la propriété B sans lever d'exception.

Mis à jour le 4 septembre 2014 bouye

Pour savoir si une propriété est déjà "bindée", c'est-à-dire si elle est liée à la valeur d'une autre propriété par une liaison simple ou unidirectionnelle, il suffit de tester la valeur retournée par sa méthode isBound(). Si cette méthode retourne true, alors cette propriété est liée à une autre et tout appel à un setter lèvera une exception.

Mis à jour le 4 septembre 2014 bouye

Pour établir une liaison bidirectionnelle entre deux propriétés de types compatibles, la propriété A et la propriété B, il suffit d'invoquer la méthode bindBidirectional() de la propriété B en passant en paramètre la propriété A.



Ce qui nous donne :

Code Java : Sélectionner tout
objet2.bProperty().bindBidirectional(objet1.aProperty());

Une fois cette liaison établie et tant qu'elle perdura, tout changement de valeur de propriété est automatiquement propagé à l'autre propriété :
  • Si on invoque un des setters de la propriété A, la valeur de la propriété B sera modifiée.
  • Si on invoque un des setters de la propriété B, la valeur de la propriété A sera modifiée.


Une propriété peut avoir plusieurs liaisons bidirectionnelles.

Code Java : Sélectionner tout
1
2
objet2.bProperty().bindBidirectional(objet1.aProperty()); 
objet2.bProperty().bindBidirectional(objet3.cProperty());

Notre première ligne de code lie bidirectionnellement B sur A.



Tandis que notre seconde ligne de code lie bidirectionnellement B sur C.



Une fois ces liaisons effectuées :
  • si on invoque un des setters de la propriété A, les valeurs des propriétés B et C sont modifiées ;
  • si on invoque un des setters de la propriété B, les valeurs des propriétés A et C sont modifiées ;
  • si on invoque un des setters de la propriété C, les valeurs des propriétés A et B sont modifiées.


Cependant les propriétés A et C ne sont pas liées directement entre elles : tout changement de valeur transite d'abord par B.

Les liaisons bidirectionnelles entre propriétés sont établies en utilisant des références et écouteurs faibles, elles n’empêchent donc pas le garbage collector de réclamer des propriétés devenues inaccessibles. Cependant, c'est une bonne pratique que de casser les liaisons bidirectionnelles devenues inutiles pour éviter des propagations en cascade de propriétés dans votre code ou encore des mises à jour ou affichages incohérents dans votre IU.

Mis à jour le 4 septembre 2014 bouye

Il suffit d'appeler la méthode unbindBidirectional() de la propriété en passant en paramètre la propriété liée.

Reprenons notre exemple de la propriété B liée bidirectionnellement à la propriété A. Si nous faisons :

Code Java : Sélectionner tout
objet2.bProperty().unbindBidirectional(objet1.aProperty());

Désormais, les changements de valeur de A ne sont plus répercutés sur la propriété B, de même que les changements de valeur de B ne sont plus répercutés sur la propriété A. Les autres liaisons bidirectionnelles que B peut avoir vers d'autres propriétés ne sont pas impactées.

Mis à jour le 4 septembre 2014 bouye

Il est en effet possible dans le code d’établir des liaisons simples et bidirectionnelles à partir d'une seule et même propriété. Rien ne l’empêche, mais ce n'est pas recommandé.



En effet une propriété qui établit une liaison simple se place dans un état dans lequel on ne peut plus appeler son setter. Si la valeur de la propriété doit être modifiée à cause d'une modification propagée via la liaison bidirectionnelle, cela peut provoquer la levée d'une exception ou placer votre graphe de propriétés liées entre elles dans un état incohérent dans lequel elles n'auraient pas les valeurs escomptées.

Mis à jour le 4 septembre 2014 bouye

Imaginons que nous ayons une propriété currentUser qui contient un objet de type Person (une personne). La classe Person dispose d'une propriété name contenant le nom de cette personne sous forme de String. Or c'est cette propriété name que nous désirons manipuler ou afficher : nous voulons donc accéder à la propriété d'une propriété.

Nous avons les cas de figure suivants :

  • si la propriété currentUser est à la valeur null, nous voulons manipuler une chaine de caractères observable qui contient null (un utilisateur null n'a pas de nom) ;
  • si la propriété currentUser est à l'utilisateur "Cyril Lacroix", nous voulons manipuler une chaine de caractères observable qui contient "Lacroix" ;
  • si la propriété currentUser est à l'utilisateur "Ingrid Etiakov", nous voulons manipuler une chaine de caractères observable qui contient "Etiakov".


Et évidemment en saisissant le moins de code possible !

Tout cela est possible en invoquant la méthode selectString() de la classe utilitaire javafx.beans.binding.Bindings.

Si nous faisons :

Code Java : Sélectionner tout
final StringBinding currentUserName = Bindings.selectString(currentUserProperty(), "name");

Nous recevons un objet de type StringBinding : une liaison vers une propriété contenant une chaine de texte. Désormais si notre utilisateur courant change de valeur, cette entité verra sa valeur automatiquement invalidée. Comme il s'agit d'une chaine de caractères observable, il est tout à fait possible de "binder" une propriété dessus, par exemple la valeur textuelle d'un label à l’écran. Lors d'une invalidation, le label changera de valeur automatiquement pour afficher le bon nom à l’écran.

Cela reviendrait grosso modo à faire :

Code Java : Sélectionner tout
final StringBinding currentUserName = currentUserProperty().get().nameProperty();

Tout en tenant compte bien sûr du cas particulier quand notre utilisateur courant n'est pas défini.

La classe utilitaire Bindings dispose de plusieurs variantes de la méthode select() pour retourner des valeurs observables contenant des objets (select()), des chaines de caractères (selectString()), des valeurs booléennes (selectBoolean()), des nombres entiers (selectInteger()), etc. contenus dans des propriétés.

Note : suivant lorsque vous invoquez une méthode selectXXX() et lorsque votre propriété source est à la valeur null, suivant votre version de JavaFX, vous pouvez être amené à avoir soit une trace d'exception ou soit un warning qui s'affiche sur la console. Cela est dû à des restes d'un code de débogage dans l'API JavaFX. L'exception n'interrompt pas l’exécution de votre code et votre binding fonctionne correctement comme décrit ci-dessus.

Mis à jour le 15 mars 2015 bouye

Il faut faire… exactement comme dans la question précédente !

En fait, il est possible de spécifier les différents niveaux de propriété que nous devons traverser jusqu'à la propriété ciblée en spécifiant les différentes étapes à traverser dans des paramètres distincts :

Code Java : Sélectionner tout
final IntegerBinding currentCountryCode = Bindings.selectInteger(currentUserProperty(), "country", "countryCode");

Cela reviendrait grosso modo à faire :

Code Java : Sélectionner tout
final IntegerBinding currentCountryCode = currentUserProperty().get().countryProperty().get().countryCodeProperty();

Si jamais, la résolution de la propriété ne peut pas traverser un niveau intermédiaire, l'objet de type IntegerBinding retourné contiendra bien sûr la valeur null.

Mis à jour le 4 septembre 2014 bouye

La classe utilitaire javafx.beans.binding.Bindings dispose de plusieurs méthodes permettant d'effectuer des opérations arithmétiques entre des propriétés numériques.

Ainsi, imaginons que nous ayons plusieurs variables x, y et z, et que nous désirions effectuer l’opération suivante :

Code : Sélectionner tout
w = 5 * x + y / z

Grâce aux méthodes de la classe Bindings, nous pouvons aisément définir le binding numérique suivant :

Code Java : Sélectionner tout
final DoubleBinding w = Bindings.multiply(5, xProperty()).add(Bindings.divide(yProperty(), zProperty());

Désormais, tout changement sur les valeurs des propriétés X, Y ou Z provoquera une invalidation de valeur numérique observable W.

Gardez cependant en tête que cette manière de procéder peut vite devenir illisible sur une équation trop longue ou trop complexe. De plus, elle n'est pas non plus très performante en nombre d'objets créés : chaque appel à une des méthodes de la classe Bindings (ici multiply(), add() et divide()) générant un nouvel objet de liaison. On lui préférera sans doute la création d'une nouvelle expression en utilisant le binding de bas niveau.

Mis à jour le 4 septembre 2014 bouye

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.