
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.
- Que sont les collections observables ?
- Comment cr�er une nouvelle instance d'une collection observable ?
- Comment convertir une collection standard en collection observable ?
- Comment recevoir les notifications de modification d'une liste observable ?
- Comment traiter les notifications de modification d'une liste observable ?
- Comment cr�er une liste observable automatiquement tri�e ?
- Comment cr�er une liste observable automatiquement filtr�e ?
- Comment recevoir les notifications de modification d'une table de hachage observable ?
- Comment traiter les notifications de modification d'une table de hachage observable ?
JavaFX introduit une nouvelle API de collections : les collections observables. Ces collections �mettent des �v�nements quand leur contenu change, que des objets sont ajout�s, retir�s ou modifi�s dans la collection. Les classes de cette API sont situ�es dans le package javafx.collections.
Il existe quatre types de collections observables fournis par l'API JavaFX :
- ObservableArray - une classe observable qui encapsule des tableaux d'entiers ou de flottants - JavaFX 8 ou ult�rieur�;
- ObservableList<T> - les listes observables�;
- ObservableMap<T> - les tables de hachage/dictionnaires observables�;
- ObservableSet<T> - les ensembles observables.
L'API SceneGraph utilise la classe ObservableList de mani�re intensive ; il est donc conseill� de s'int�resser � leur fonctionnement pour mieux comprendre le fonctionnement des gestionnaires de mise en page, des listes, arbres et tables graphiques, etc.
� l'exception d'ObservableArray qui lui est propre, cette API reste compatible avec l'API standard de collections de Java ainsi qu'avec toutes les am�liorations introduites dans le JDK8 (streams).
La classe utilitaire javafx.collections.FXCollections contient des m�thodes permettant de cr�er de nouvelles collections observables.
Par exemple :
Code Java : | S�lectionner tout |
final ObservableList<Person> people = FXCollections.observableArrayList();
Ce code cr�era une nouvelle liste observable vide.
Il est �galement possible de fournir des �l�ments permettant d�initialiser le contenu de la liste :
Code Java : | S�lectionner tout |
final ObservableList<Person> people = FXCollections.observableArrayList(person1, person2, person3);
En interne, la liste est stock�e en utilisant une instance de la classe java.util.ArrayList de l'API de collection standard Java.
La classe utilitaire javafx.collections.FXCollections contient des m�thodes permettant d'empaqueter une collection Java standard en collection observable.
Par exemple :
Code Java : | S�lectionner tout |
1 2 3 4 | final Map<<PhoneNumber, Person> phoneBook = new HashMap<>(); // Remplissage de l'annuaire. [...] final ObservableMap<PhoneNumber, Person> phoneBookObservable = FXCollections.observableMap(phoneBook); |
Ici, notre table de hachage est d�sormais empaquet�e dans une table de hachage observable.
De la m�me mani�re, il est possible de cr�er des listes observables utilisant une instance de LinkedList comme stockage interne au lieu d'une instance de ArrayList. Par exemple :
Code Java : | S�lectionner tout |
final ObservableList<Car> carList = FXCollections.observableList(new LinkedList());
Note : il va de soi que pour pouvoir �mettre correctement des �v�nements en cas de modification, ce sont les versions observables des collections qui doivent �tre d�sormais manipul�es. Toute manipulation de la version non observable de la collection passera inaper�ue.
Pour recevoir les notifications de modification d'une ObservableList<T>, il faut lui ajouter un �couteur de type javafx.collections.ListChangeListener<T> et traiter l'objet de type javafx.collections.ListChangeListener.Change<? extends T> pass� en param�tre de sa m�thode onChanged().
Commen�ons par cr�er une liste observable :
Code Java : | S�lectionner tout |
final ObservableList<String> names = FXCollections.observableArrayList("Andr�", "�lodie", "Jasmina", "Malik", "Val�rie", "Yvana");
Maintenant, nous allons lui ajouter un �couteur de type ListChangeListener:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | names.addListener(new ListChangeListener<String>() { @Override public void onChanged(ListChangeListener.Change<? extends String> change) { // Traitement des changements ici. } }); |
Nous pouvons �galement faire la m�me chose en utilisant les expressions lambda du JDK8 :
Code Java : | S�lectionner tout |
1 2 3 | names.addListener((ListChangeListener.Change<? extends String> change) -> { // Traitement des changements ici. }); |
Ici, il est n�cessaire de sp�cifier le type de l'argument de l'expression lambda, car il existe �galement une variante de la m�thode addListener() acceptant un InvalidationListener dans la classe ObservableList. Sp�cifier le type permet de r�soudre l�ambig�it� sur la m�thode qui doit �tre invoqu�e.
Pour am�liorer les performances et minimiser le nombre d��v�nements publi�s, l'objet change re�u dans la m�thode onChanged() d'un ListChangeListener est en fait un rapport agr�g� contenant les r�centes modifications sur la liste observable. Les diverses modifications devront �tre trait�es dans une boucle de style :
Code Java : | S�lectionner tout |
1 2 3 | while(change.next()) { // Traiter chaque changement s�par�ment ici. } |
Il ne faut jamais invoquer de m�thodes de l'objet change sans avoir invoqu� sa m�thode next() au pr�alable !
Dans un objet de type ListChangeListener.Change, nous pouvons recevoir cinq types de notifications :
- Remplacement : une ou plusieurs valeurs ont �t� remplac�es par d'autres ;
- Permutation: une ou plusieurs valeurs ont �chang� leur place dans la liste avec d'autres (qui �taient �galement dans la liste) ;
- Mise � jour : une ou plusieurs valeurs ont �t� modifi�es. Ce type de notification est optionnel et peut ne pas �tre pris en charge par tous les types de listes observables ;
- Ajout : une ou plusieurs valeurs ont �t� ajout�es dans la liste ;
- Suppression : une ou plusieurs valeurs ont �t� supprim�es dans la liste.
Ces types ne sont pas exclusifs : plusieurs types peuvent �tre actifs en m�me temps.
Ajoutons l��couteur suivant sur notre liste de noms :
Code Java : | S�lectionner tout |
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 | names.addListener((ListChangeListener.Change<? extends String> change) -> { System.out.println("+Notification"); while (change.next()) { if (change.wasReplaced()) { System.out.printf("++Remplacement %d %d", change.getFrom(), change.getTo()).println(); } if (change.wasPermutated()) { System.out.printf("++Permutation %d %d", change.getFrom(), change.getTo()).println(); for (int index = change.getFrom() ; index < change.getTo() ; index++) { System.out.printf("%d -> %d", index, change.getPermutation(index)).println(); } } if (change.wasUpdated()) { System.out.printf("++Mise � jour %d %d", change.getFrom(), change.getTo()).println(); } if (change.wasAdded()) { System.out.println("++Ajout"); change.getAddedSubList().forEach(value -> System.out.printf("\"%s\" a �t� ajout�.", value).println()); } if (change.wasRemoved()) { System.out.println("++Retrait"); change.getRemoved().forEach(value -> System.out.printf("\"%s\" a �t� supprim�.", value).println()); } } System.out.println(); }); |
Ajoutons maintenant quelques noms dans la liste :
Code Java : | S�lectionner tout |
names.addAll("Henri", "Oscar", "Manon");
La sortie de cette op�ration est :
Code : | S�lectionner tout |
1 2 3 4 5 | +Notification ++Ajout "Henri" a �t� ajout�. "Oscar" a �t� ajout�. "Manon" a �t� ajout� |
Retirons maintenant des �l�ments de la liste :
Code Java : | S�lectionner tout |
names.removeAll("Andr�", "�lodie");
La sortie de cette op�ration est :
Code : | S�lectionner tout |
1 2 3 4 | +Notification ++Retrait "Andr�" a �t� supprim�. "�lodie" a �t� supprim�. |
Rempla�ons maintenant un �l�ment de la liste par un autre :
Code Java : | S�lectionner tout |
names.set(0, "Barbara");
La sortie de cette op�ration est :
Code : | S�lectionner tout |
1 2 3 4 5 6 | +Notification ++Remplacement 0 1 ++Ajout "Barbara" a �t� ajout�. ++Retrait "Jasmina" a �t� supprim�. |
Nous allons maintenant trier la liste :
Code Java : | S�lectionner tout |
FXCollections.sort(names);
La sortie de cette op�ration est :
Code : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 | +Notification ++Permutation 0 7 0 -> 0 1 -> 2 2 -> 5 3 -> 6 4 -> 1 5 -> 4 6 -> 3 |
� partir du JDK 8, il est possible de cr�er une liste observable automatiquement tri�e en empaquetant une liste observable source dans une instance de la classe javafx.collections.transformation.SortedList<T>.
Par exemple :
Code Java : | S�lectionner tout |
1 2 | final ObservableList<String> names = FXCollections.observableArrayList("Yvana", "�lodie", "Andr�", "Jasmina", "Malik", "Val�rie"); final SortedList<String> sortedNames = new SortedList(names); |
Ici le contenu de la nouvelle liste n'est initialement pas tri� et adopte donc le m�me ordre d��l�ments que dans la liste source.
Il est possible de changer l'ordre ou le crit�re du tri en sp�cifiant une instance de la classe java.util.Comparator dans la propri�t� comparator de la liste tri�e :
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | sortedNames.setComparator(new Comparator<String>(){ @Override public int compare(String o1, String o2) { return o1.compareTo(o2); } }); |
Ou :
Code Java : | S�lectionner tout |
sortedNames.setComparator(String::compareTo);
Ce qui nous donne :
Code : | S�lectionner tout |
[Andr�, Jasmina, Malik, Val�rie, Yvana, �lodie]
Ici, la liste tri�e contient donc les m�mes �l�ments que la liste source, mais tri�s dans un ordre lexicographique.
La liste sortedNames sera toujours tri�e, m�me si on ajoute, retire ou permute des �l�ments de la liste names. Tout changement sur la liste source est automatiquement r�percut� sur la liste tri�e. La liste tri�e �tant elle-m�me une liste observable, elle �mettra les �v�nements appropri�s en cas de modifications de la liste source qui ont des r�percussions sur son contenu.
� partir du JDK 8, il est possible de cr�er une liste observable automatiquement filtr�e en empaquetant une liste observable dans une instance de la classe javafx.collections.transformation.FilteredList<T>.
Par exemple :
Code Java : | S�lectionner tout |
1 2 | final ObservableList<String> names = FXCollections.observableArrayList("Yvana", "�lodie", "Andr�", "Jasmina", "Malik", "Val�rie"); final FilteredList<String> filteredNames = new FilteredList(names); |
Ici, la liste filteredNames est initialement vide, car l'absence de filtre fait qu'elle rejette tous les �l�ments de la liste source names.
Il est possible de sp�cifier une instance de la classe java.util.function.Predicate dans la propri�t� predicate de la liste filtr�e pour rendre le filtrage op�rationnel :
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | filteredNames.setPredicate(new Predicate<String>() { @Override public boolean test(String value) { return value.length() > 5; } }); |
Ou :
Code Java : | S�lectionner tout |
filteredNames.setPredicate(value -> value.length() > 5);
Ce qui nous donne :
Code : | S�lectionner tout |
[�lodie, Jasmina, Val�rie]
Ici, seuls les noms dont la longueur d�passe cinq caract�res sont membres de la liste filtr�e.
La liste filteredNames sera toujours automatiquement filtr�e, m�me si on ajoute, retire ou permute des �l�ments de la liste names. Tout changement sur la liste source est automatiquement r�percut� sur la liste filtr�e. La liste filtr�e �tant elle-m�me une liste observable, elle �mettra les �v�nements appropri�s en cas de modifications de la liste source qui ont des r�percussions sur son contenu.
Pour recevoir les notifications de modification d'une ObservableMap<K, V>, il faut lui ajouter un �couteur de type javafx.collections.MapChangeListener<K, V> et traiter l'objet de type javafx.collections.MapChangeListener.Change<? extends K, ? extends V> pass� en param�tre de sa m�thode onChanged().
Commen�ons par cr�er une liste observable :
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | final Map<Integer, String> source = new HashMap(); source.put(0, "Anthony"); source.put(1, "Antoinette"); source.put(2, "J�r�me"); source.put(3, "Karine"); source.put(4, "Patrick"); final ObservableMap<Integer, String> users = FXCollections.observableMap(source); |
Maintenant, nous allons lui ajouter un �couteur de type ListChangeListener :
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | users.addListener(new MapChangeListener<Integer, String>() { @Override public void onChanged(MapChangeListener.Change<? extends Integer, ? extends String> change) { // Traitement des changements ici. } }); |
Nous pouvons �galement faire la m�me chose en utilisant les expressions lambda du JDK8 :
Code Java : | S�lectionner tout |
1 2 3 | users.addListener((MapChangeListener.Change<? extends Integer, ? extends String> change) -> { // Traitement des changements ici. }); |
Ici, il est n�cessaire de sp�cifier le type de l'argument de l'expression lambda, car il existe �galement une variante de la m�thode addListener() acceptant un InvalidationListener dans la classe MapList. Sp�cifier le type permet de r�soudre l�ambig�it� sur la m�thode qui doit �tre invoqu�e.
La gestion des �v�nements sur une table de hachage observable est moins �volu�e que sur les listes observables. Ici l'objet change re�u dans la m�thode onChanged() d'un MapChangeListener contient une seule notification d��v�nement :
Dans un objet de type MapChangeListener.Change, nous pouvons recevoir deux types de notifications :
- Ajout : une valeur a �t� ajout�e dans la table ;
- Suppression : une valeur a �t� retir�e de la table.
Ces types ne sont pas exclusifs : plusieurs types peuvent �tre actifs en m�me temps.
Ajoutons l��couteur suivant sur notre table d'utilisateurs :
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 | users.addListener((MapChangeListener.Change<? extends Integer, ? extends String> change) -> { System.out.println("+Notification"); if (change.wasAdded()) { System.out.printf("\"%s\" a �t� ajout�.", change.getValueAdded()).println(); } if (change.wasRemoved()) { System.out.printf("\"%s\" a �t� supprim�.", change.getValueRemoved()).println(); } System.out.println(); }); |
Ajoutons maintenant quelques noms dans la table :
Code Java : | S�lectionner tout |
1 2 | users.put(5, "Ren�e"); users.put(6, "Herv�"); |
La sortie de ces op�rations est :
Code : | S�lectionner tout |
1 2 3 4 5 | +Notification "Ren�e" a �t� ajout�. +Notification "Herv�" a �t� ajout�. |
Retirons maintenant des �l�ments de table :
Code Java : | S�lectionner tout |
1 2 | users.remove(0); users.remove(1); |
La sortie de cette op�ration est :
Code : | S�lectionner tout |
1 2 3 4 5 | +Notification "Anthony" a �t� supprim�. +Notification "Antoinette" a �t� supprim�. |
Rempla�ons maintenant un �l�ment de la table par un autre :
Code Java : | S�lectionner tout |
users.put(3, "Annie");
La sortie de cette op�ration est :
Code : | S�lectionner tout |
1 2 3 | +Notification "Annie" a �t� ajout�. "Karine" a �t� supprim�. |
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 �aLes 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 � 2025 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.