ListView de JavaFX pour afficher des listes d'éléments. Vous découvrirez comment afficher des données, gérer la sélection, lier une ListView à un modèle de données, et personnaliser l'affichage avec une CellFactory. Le ListView est l'un des composants les plus utilisés pour afficher des collections de données.
6.2ListView
6.2.1 – Affichage et sélection
Le ListView est un composant JavaFX qui affiche une liste d'éléments dans une zone défilable. Il permet à l'utilisateur de sélectionner un ou plusieurs éléments et d'interagir avec la liste. C'est le composant idéal pour afficher des collections de données.
🎯 Caractéristiques du ListView
Le ListView offre plusieurs fonctionnalités :
- Affichage vertical : Les éléments sont affichés en colonne, un par ligne
- Défilement automatique : Si la liste est longue, une barre de défilement apparaît automatiquement
- Sélection simple ou multiple : L'utilisateur peut sélectionner un ou plusieurs éléments
- Liaison avec ObservableList : Se met Ă jour automatiquement quand la liste change
- Personnalisation : Vous pouvez personnaliser l'affichage avec une CellFactory
📝 Créer une ListView simple
Pour créer une ListView, vous devez d'abord créer une ObservableList et la lier à la ListView :
Exemple 1 : ListView basique avec String
package application;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class MainController {
@FXML
private ListView<String> listViewItems;
private ObservableList<String> items;
@FXML
private void initialize() {
// Créer l'ObservableList avec des éléments
items = FXCollections.observableArrayList(
"Pomme", "Banane", "Orange", "Fraise", "Cerise"
);
// Lier la ListView Ă l'ObservableList
listViewItems.setItems(items);
// Maintenant, la ListView affiche les 5 éléments
}
}
•
ListView<String> : Crée une ListView qui affiche des String•
setItems(items) : Lie l'ObservableList à la ListView• Les éléments sont affichés automatiquement dans la ListView
📝 Gérer la sélection
Le ListView permet de gérer la sélection d'éléments. Vous pouvez récupérer l'élément sélectionné ou écouter les changements de sélection :
Exemple 2 : Récupérer l'élément sélectionné
@FXML
private void afficherSelection() {
// Récupérer l'élément sélectionné
String itemSelectionne = listViewItems.getSelectionModel().getSelectedItem();
if (itemSelectionne != null) {
System.out.println("Élément sélectionné : " + itemSelectionne);
} else {
System.out.println("Aucun élément sélectionné");
}
}
@FXML
private void afficherIndex() {
// Récupérer l'index de l'élément sélectionné
int indexSelectionne = listViewItems.getSelectionModel().getSelectedIndex();
if (indexSelectionne >= 0) {
System.out.println("Index sélectionné : " + indexSelectionne);
} else {
System.out.println("Aucun élément sélectionné");
}
}
Exemple 3 : Écouter les changements de sélection
@FXML
private void initialize() {
items = FXCollections.observableArrayList("Pomme", "Banane", "Orange");
listViewItems.setItems(items);
// Écouter les changements de sélection
listViewItems.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal) -> {
if (newVal != null) {
System.out.println("Nouvelle sélection : " + newVal);
System.out.println("Ancienne sélection : " + oldVal);
} else {
System.out.println("Sélection supprimée");
}
});
}
📝 Sélection multiple
Par défaut, la ListView permet la sélection d'un seul élément. Pour activer la sélection multiple :
@FXML
private void initialize() {
items = FXCollections.observableArrayList("Pomme", "Banane", "Orange", "Fraise");
listViewItems.setItems(items);
// Activer la sélection multiple
listViewItems.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
// Maintenant, l'utilisateur peut sélectionner plusieurs éléments
// en maintenant Ctrl (ou Cmd sur Mac) et en cliquant
}
@FXML
private void afficherSelectionsMultiples() {
// Récupérer tous les éléments sélectionnés
ObservableList<String> selections = listViewItems.getSelectionModel().getSelectedItems();
System.out.println("Éléments sélectionnés : " + selections);
System.out.println("Nombre : " + selections.size());
}
•
SelectionMode.SINGLE : Sélection d'un seul élément (par défaut)•
SelectionMode.MULTIPLE : Sélection de plusieurs éléments (Ctrl/Cmd + clic)
📝 Méthodes utiles du SelectionModel
Le SelectionModel offre plusieurs méthodes pour gérer la sélection :
SelectionModel<String> selectionModel = listViewItems.getSelectionModel();
// Récupérer la sélection
String selected = selectionModel.getSelectedItem(); // Élément sélectionné
int index = selectionModel.getSelectedIndex(); // Index sélectionné
ObservableList<String> selectedItems = selectionModel.getSelectedItems(); // Tous les éléments sélectionnés
// Modifier la sélection
selectionModel.select(0); // Sélectionner le premier élément
selectionModel.select("Pomme"); // Sélectionner par valeur
selectionModel.clearSelection(); // Désélectionner tout
selectionModel.selectNext(); // Sélectionner l'élément suivant
selectionModel.selectPrevious(); // Sélectionner l'élément précédent
// Vérifier la sélection
boolean hasSelection = selectionModel.isEmpty(); // Vérifier si rien n'est sélectionné
int count = selectionModel.getSelectedIndices().size(); // Nombre d'éléments sélectionnés
📝 Exemple complet : ListView avec sélection
Créons un exemple complet qui affiche une liste et permet de gérer la sélection :
MainController.java
package application;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.SelectionMode;
public class MainController {
@FXML
private ListView<String> listViewItems;
@FXML
private TextField txtNouvelItem;
@FXML
private Button btnAjouter;
@FXML
private Button btnSupprimer;
@FXML
private Label lblSelection;
private ObservableList<String> items;
@FXML
private void initialize() {
// Créer l'ObservableList
items = FXCollections.observableArrayList(
"Pomme", "Banane", "Orange", "Fraise", "Cerise"
);
// Lier Ă la ListView
listViewItems.setItems(items);
// Activer la sélection multiple (optionnel)
listViewItems.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
// Écouter les changements de sélection
listViewItems.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal) -> {
if (newVal != null) {
lblSelection.setText("Sélectionné : " + newVal);
} else {
lblSelection.setText("Aucune sélection");
}
});
// Initialiser le label
lblSelection.setText("Aucune sélection");
}
@FXML
private void ajouterItem() {
String nouvelItem = txtNouvelItem.getText().trim();
if (!nouvelItem.isEmpty()) {
items.add(nouvelItem);
txtNouvelItem.clear();
}
}
@FXML
private void supprimerItem() {
String selectionne = listViewItems.getSelectionModel().getSelectedItem();
if (selectionne != null) {
items.remove(selectionne);
}
}
@FXML
private void afficherSelection() {
ObservableList<String> selections = listViewItems.getSelectionModel().getSelectedItems();
if (!selections.isEmpty()) {
System.out.println("Éléments sélectionnés : " + selections);
}
}
}
• La ListView est liée à une ObservableList avec
setItems()• Le SelectionModel permet de gérer la sélection
• Un listener sur
selectedItemProperty() détecte les changements• La sélection multiple est activée avec
setSelectionMode()
💡 Points clés à retenir
- ListView : Composant pour afficher une liste d'éléments
- setItems() : Lie une ObservableList Ă la ListView
- getSelectionModel() : Accède au modèle de sélection
- getSelectedItem() : Récupère l'élément sélectionné (sélection simple)
- getSelectedItems() : Récupère tous les éléments sélectionnés (sélection multiple)
- selectedItemProperty() : Propriété observable pour écouter les changements
- SelectionMode : SINGLE (par défaut) ou MULTIPLE
ObservableList avec ListView pour bénéficier de la mise à jour automatique. Testez la sélection simple et multiple pour bien comprendre les différences !
6.2.2 – Liaison à un modèle simple
Dans cette section, vous allez apprendre à lier une ListView à un modèle de données simple. Au lieu d'afficher des String, vous afficherez des objets personnalisés. JavaFX utilise la méthode toString() de vos objets pour les afficher dans la ListView.
🎯 Pourquoi utiliser un modèle ?
Utiliser un modèle (classe personnalisée) au lieu de String permet de :
- Stockage de données complexes : Chaque élément peut contenir plusieurs propriétés
- Organisation : Les données sont structurées et typées
- Extensibilité : Facile d'ajouter de nouvelles propriétés
- Réutilisabilité : Le même modèle peut être utilisé dans plusieurs composants
📝 Exemple : Classe Personne
Créons une classe Personne simple pour illustrer :
Personne.java
package application;
public class Personne {
private String nom;
private String prenom;
private int age;
public Personne(String nom, String prenom, int age) {
this.nom = nom;
this.prenom = prenom;
this.age = age;
}
// Getters
public String getNom() { return nom; }
public String getPrenom() { return prenom; }
public int getAge() { return age; }
// Setters
public void setNom(String nom) { this.nom = nom; }
public void setPrenom(String prenom) { this.prenom = prenom; }
public void setAge(int age) { this.age = age; }
// Méthode toString() - Utilisée par la ListView pour afficher l'objet
@Override
public String toString() {
return prenom + " " + nom + " (" + age + " ans)";
}
}
• La méthode
toString() est utilisée par la ListView pour afficher chaque élément• Si vous ne redéfinissez pas
toString(), la ListView affichera quelque chose comme "Personne@123abc"• Redéfinissez toujours
toString() pour avoir un affichage lisible
📝 Utiliser Personne dans une ListView
MainController.java
package application;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class MainController {
@FXML
private ListView<Personne> listViewPersonnes;
@FXML
private Label lblDetails;
private ObservableList<Personne> personnes;
@FXML
private void initialize() {
// Créer l'ObservableList de Personne
personnes = FXCollections.observableArrayList(
new Personne("Dupont", "Jean", 25),
new Personne("Martin", "Marie", 30),
new Personne("Bernard", "Pierre", 28),
new Personne("Dubois", "Sophie", 32)
);
// Lier Ă la ListView
listViewPersonnes.setItems(personnes);
// Écouter les changements de sélection
listViewPersonnes.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal) -> {
if (newVal != null) {
// Afficher les détails de la personne sélectionnée
String details = String.format("Nom : %s\nPrénom : %s\nÂge : %d ans",
newVal.getNom(), newVal.getPrenom(), newVal.getAge());
lblDetails.setText(details);
} else {
lblDetails.setText("Aucune personne sélectionnée");
}
});
}
@FXML
private void ajouterPersonne() {
Personne nouvelle = new Personne("Nouveau", "Nom", 20);
personnes.add(nouvelle);
// La ListView se met Ă jour automatiquement !
}
@FXML
private void supprimerPersonne() {
Personne selectionnee = listViewPersonnes.getSelectionModel().getSelectedItem();
if (selectionnee != null) {
personnes.remove(selectionnee);
}
}
}
•
ListView<Personne> : ListView qui affiche des objets Personne•
ObservableList<Personne> : Liste observable de Personne• La ListView appelle
toString() pour afficher chaque Personne• Quand vous sélectionnez une Personne, vous pouvez accéder à toutes ses propriétés
📝 Récupérer les données de l'élément sélectionné
Une fois qu'un élément est sélectionné, vous pouvez accéder à toutes ses propriétés :
@FXML
private void afficherDetails() {
Personne selectionnee = listViewPersonnes.getSelectionModel().getSelectedItem();
if (selectionnee != null) {
// Accéder aux propriétés de l'objet
String nom = selectionnee.getNom();
String prenom = selectionnee.getPrenom();
int age = selectionnee.getAge();
System.out.println("Nom complet : " + prenom + " " + nom);
System.out.println("Âge : " + age + " ans");
}
}
@FXML
private void modifierPersonne() {
Personne selectionnee = listViewPersonnes.getSelectionModel().getSelectedItem();
if (selectionnee != null) {
// Modifier les propriétés
selectionnee.setNom("Nouveau nom");
selectionnee.setAge(30);
// Pour que la ListView se mette Ă jour, il faut appeler refresh()
// (sauf si vous utilisez un extractor - voir section 6.1.3)
listViewPersonnes.refresh();
}
}
• Si vous modifiez les propriétés d'un objet dans la liste, la ListView ne se met pas à jour automatiquement
• Vous devez appeler
listView.refresh() pour forcer la mise à jour• Ou utilisez un extractor avec ObservableList (voir section 6.1.3) pour une mise à jour automatique
💡 Points clés à retenir
- Modèle personnalisé : Créez une classe pour représenter vos données
- toString() : Redéfinissez cette méthode pour l'affichage dans la ListView
- ObservableList<Type> : Utilisez le type de votre modèle
- getSelectedItem() : Retourne l'objet complet, pas juste une String
- refresh() : Nécessaire si vous modifiez les propriétés d'un objet
- Extractor : Pour une mise Ă jour automatique (voir section 6.1.3)
6.2.3 – CellFactory simple (optionnel)
Par défaut, la ListView affiche chaque élément en appelant sa méthode toString(). Si vous voulez personnaliser l'affichage (couleurs, icônes, mise en forme, etc.), vous pouvez utiliser une CellFactory. Cette section présente une approche simple pour personnaliser l'affichage.
toString() est suffisant. Utilisez une CellFactory seulement si vous avez besoin de personnaliser l'affichage.
🎯 Quand utiliser une CellFactory ?
Utilisez une CellFactory quand vous voulez :
- Personnaliser l'apparence : Couleurs, polices, styles différents selon les éléments
- Ajouter des icônes : Afficher des images ou des icônes à côté du texte
- Mise en forme avancée : Disposition complexe avec plusieurs éléments
- Affichage conditionnel : Afficher différemment selon certaines conditions
📝 Exemple 1 : CellFactory simple avec Label
Créons une CellFactory simple qui personnalise l'affichage avec des couleurs :
MainController.java
package application;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.util.Callback;
public class MainController {
@FXML
private ListView<String> listViewItems;
private ObservableList<String> items;
@FXML
private void initialize() {
items = FXCollections.observableArrayList(
"Pomme", "Banane", "Orange", "Fraise", "Cerise"
);
listViewItems.setItems(items);
// Définir une CellFactory pour personnaliser l'affichage
listViewItems.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
@Override
public ListCell<String> call(ListView<String> param) {
return new ListCell<String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else {
// Créer un Label personnalisé
Label label = new Label(item);
// Appliquer des styles selon l'élément
if (item.startsWith("P")) {
label.setStyle("-fx-text-fill: red; -fx-font-weight: bold;");
} else if (item.startsWith("B")) {
label.setStyle("-fx-text-fill: yellow; -fx-font-weight: bold;");
} else {
label.setStyle("-fx-text-fill: blue;");
}
setGraphic(label);
}
}
};
}
});
}
}
Version lambda (plus simple)
@FXML
private void initialize() {
items = FXCollections.observableArrayList("Pomme", "Banane", "Orange");
listViewItems.setItems(items);
// Version lambda (plus simple)
listViewItems.setCellFactory(listView -> new ListCell<String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
} else {
setText(item);
// Appliquer un style
if (item.length() > 5) {
setStyle("-fx-text-fill: blue; -fx-font-weight: bold;");
} else {
setStyle("-fx-text-fill: black;");
}
}
}
});
}
•
setCellFactory() : Définit comment chaque cellule est créée•
updateItem() : Méthode appelée pour mettre à jour chaque cellule•
empty : Indique si la cellule est vide (pour les cellules de fin de liste)•
setText() ou setGraphic() : Définit le contenu de la cellule
📝 Exemple 2 : CellFactory avec objets personnalisés
Créons une CellFactory pour afficher des objets Personne avec un style personnalisé :
package application;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.HBox;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class MainController {
@FXML
private ListView<Personne> listViewPersonnes;
private ObservableList<Personne> personnes;
@FXML
private void initialize() {
personnes = FXCollections.observableArrayList(
new Personne("Dupont", "Jean", 25),
new Personne("Martin", "Marie", 30),
new Personne("Bernard", "Pierre", 28)
);
listViewPersonnes.setItems(personnes);
// CellFactory pour Personne
listViewPersonnes.setCellFactory(listView -> new ListCell<Personne>() {
@Override
protected void updateItem(Personne personne, boolean empty) {
super.updateItem(personne, empty);
if (empty || personne == null) {
setText(null);
setGraphic(null);
} else {
// Créer un HBox avec plusieurs Labels
HBox hbox = new HBox(10);
Label lblNom = new Label(personne.getPrenom() + " " + personne.getNom());
lblNom.setStyle("-fx-font-weight: bold;");
Label lblAge = new Label("(" + personne.getAge() + " ans)");
lblAge.setStyle("-fx-text-fill: gray;");
// Style selon l'âge
if (personne.getAge() < 25) {
hbox.setStyle("-fx-background-color: #e3f2fd;");
} else if (personne.getAge() < 30) {
hbox.setStyle("-fx-background-color: #f3e5f5;");
} else {
hbox.setStyle("-fx-background-color: #fff3e0;");
}
hbox.getChildren().addAll(lblNom, lblAge);
setGraphic(hbox);
}
}
});
}
}
•
updateItem() est appelée pour chaque cellule• Toujours vérifier
empty et null• Utilisez
setGraphic() pour un contenu personnalisé (HBox, VBox, etc.)• Utilisez
setText() pour un simple texte• Vous pouvez appliquer des styles conditionnels selon les propriétés de l'objet
📝 Exemple 3 : CellFactory avec icônes
Vous pouvez aussi ajouter des icĂ´nes ou des images dans les cellules :
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
listViewItems.setCellFactory(listView -> new ListCell<String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else {
// Créer un HBox avec icône et texte
HBox hbox = new HBox(10);
// Ajouter une icĂ´ne (exemple)
ImageView icon = new ImageView(new Image("file:icon.png"));
icon.setFitWidth(16);
icon.setFitHeight(16);
Label label = new Label(item);
hbox.getChildren().addAll(icon, label);
setGraphic(hbox);
}
}
});
💡 Points clés à retenir
- CellFactory : Permet de personnaliser l'affichage de chaque cellule
- setCellFactory() : Définit la CellFactory pour la ListView
- updateItem() : Méthode appelée pour mettre à jour chaque cellule
- empty : Vérifiez toujours si la cellule est vide
- setText() : Pour un affichage texte simple
- setGraphic() : Pour un affichage personnalisé (HBox, VBox, etc.)
- Optionnel : Utilisez seulement si vous avez besoin de personnalisation
- âś… Toujours appeler
super.updateItem()en premier - ✅ Toujours vérifier
emptyetnull - ✅ Réinitialiser avec
setText(null)etsetGraphic(null)si vide - âś… La CellFactory est optionnelle - utilisez
toString()si c'est suffisant
toString() est suffisant !