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.
- Comment ajouter des valeurs dans une TableView ?
- Comment savoir quand une valeur est sélectionnée dans une TableView ?
- Comment sélectionner une valeur dans une TableView ?
- Comment faire pour que les colonnes occupent tout l'espace horizontal de la TableView ?
- Comment désactiver le tri automatique sur les colonnes ?
- Comment ajouter des colonnes dans une TableView ?
- Comment faire des sous-colonnes ?
- Qu'est-ce qu'une fabrique à valeurs ?
- Comment changer l'apparence des objets contenus dans une TableView ?
- Comment activer l'édition sur une TableView ?
- Comment afficher des cases à cocher pour les valeurs booléennes dans une TableView ?
- Comment afficher des boites déroulantes dans une TableView ?
Pour ajouter des valeurs dans une TableView, il suffit de les ajouter dans sa liste observable items.
Par exemple :
Code Java : | Sélectionner tout |
1 2 | final TableView<Car> tableView = new TableView(); tableView .getItems().setAll(car1, car2, car3, car4); |
Il est possible de retirer des valeurs de la table graphique en les retirant de sa liste observable items.
Note : oui, la table graphique n'est en fait qu'une liste de valeurs. Chaque colonne est en fait une vue qui affiche une donnée issue, extraite ou transformée à partir d'une des valeurs contenues dans la table.
Pour savoir quand une valeur est sélectionnée dans une TableView, il faut récupérer le modèle de sélection dans la table en invoquant sa méthode getSelectionModel() et écouter les changements de valeur de sa propriété selectedIndex ou selectedItem avec écouteur de type InvalidationListener ou un ChangeListener.
Par exemple :
Code Java : | Sélectionner tout |
1 2 | tableView.getSelectionModel().selectedIndexProperty().addListener(observable -> System.out.printf("Indice sélectionné: %d", tableView.getSelectionModel().getSelectedIndex()).println()); tableView.getSelectionModel().selectedItemProperty().addListener(observable -> System.out.printf("Valeur sélectionnée: %d", tableView.getSelectionModel().getSelectedItem()).println()); |
Pour sélectionner une valeur dans une TableView, il faut récupérer le modèle de sélection de la table graphique en invoquant sa méthode getSelectionModel(). On peut ensuite invoquer une des variantes de la méthode select() pour sélectionner un indice ou une valeur donnée.
Par exemple :
Code Java : | Sélectionner tout |
tableView.getSelectionModel().select(car1);
Cela sélectionnera toutes les colonnes présentes sur la ligne qui affiche cette valeur.
Pour faire que les colonnes occupent tout l'espace horizontal de la TableView, il faut modifier la valeur de la propriété columnResizePolicy de la table graphique. Cette propriété accepte un callback qui permet d'effectuer la mise en page des colonnes. Cependant, de base, deux implémentations sont fournies prêtes à l'emploi dans la classe TableView :
- TableView.UNCONSTRAINED_RESIZE_POLICY - la valeur par défaut : la mise en page des colonnes dépend de leur largeur préférée ;
- TableView.CONSTRAINED_RESIZE_POLICY - les colonnes sont redimensionnées pour occuper toute la largeur de la table.
Par exemple :
Code Java : | Sélectionner tout |
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
Pour désactiver le tri automatique sur les colonnes qui se déclenche lors que l'utilisateur clique sur l’entête d'une colonne avec la souris, il faut modifier la propriété sortable de cette colonne et lui donner une valeur false.
Par exemple :
Code Java : | Sélectionner tout |
colorColumn.setSortable(false);
Initialement, une TableView ne contient aucune colonne. Pour ajouter des colonnes dans une table, il faut créer des objets de type javafx.scene.control.TableColumn<S, T> et les ajouter dans la liste observable columns de la table.
Ici :
- S est le type des objets contenus dans l'instance de TableView ;
- T est le type des objets qui seront affichés ou édités dans la colonne.
Par exemple :
Code Java : | Sélectionner tout |
1 2 | final TableColumn<Car, String> modelColumn = new TableColumn<>("Modèle"); tableView.getColumns().setAll(modelColumn); |
Ici, nous avons ajouté dans la table graphique une colonne nommée « Modèle » qui pour chaque objet de type Car présent dans la table affichera un objet de type String (le modèle de la voiture).
Nous pouvons également ajouter quelques colonnes supplémentaires en suivant le même principe :
Code Java : | Sélectionner tout |
1 2 3 4 5 | final TableColumn<Car, String> brandColumn = new TableColumn<>("Marque"); final TableColumn<Car, Color> colorColumn = new TableColumn<>("Couleur"); final TableColumn<Car, Integer> seatsColumn = new TableColumn<>("Sièges"); final TableColumn<Car, Integer> doorsColumn = new TableColumn<>("Portes"); tableView.getColumns().addAll(brandColumn, colorColumn, seatsColumn, doorsColumn); |
ce qui nous donne :
Pour retirer des colonnes, il suffit de les retirer la liste observable columns de la table.
Pour faire des sous-colonnes, il suffit d'ajouter des colonnes dans la liste observable columns d'une autre colonne.
Par exemple :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 | final TableColumn<Car, String> modelColumn = new TableColumn<>("Modèle"); final TableColumn<Car, String> brandColumn = new TableColumn<>("Marque"); final TableColumn<Car, Color> colorColumn = new TableColumn<>("Couleur"); final TableColumn<Car, Integer> seatsColumn = new TableColumn<>("Sièges"); final TableColumn<Car, Integer> doorsColumn = new TableColumn<>("Portes"); final TableColumn<Car, ?> optionsColumn = new TableColumn<>("Options"); optionsColumn.getColumns().setAll(colorColumn, seatsColumn, doorsColumn); tableView.getColumns().setAll(modelColumn, brandColumn, optionsColumn); |
Ce qui nous donne :
Ici, les colonnes « Couleur », « Sièges » et « Portes » sont incluses dans la colonne « Options ».
Pour retirer des colonnes, il suffit de les retirer la liste observable columns de la colonne mère.
Une fabrique à valeurs (value factory en anglais) est un callback placé sur une colonne de type <S, T> et qui permet de retrouver une valeur de type T à partir d'un objet source de type S contenu dans la table.
Les objets de type TableColumn<S, T> disposent d'une propriété cellValueFactory qui permet de spécifier ce callback (à ne pas confondre avec la propriété cellFactory).
Par exemple :
- si l'objet est accessible par une propriété JavaFX, c'est très simple, nous pouvons créer une nouvelle instance de la classe javafx.scene.control.cell.PropertyValueFactory<S, T> qui se chargera pour nous d’accéder à la propriété :
Code Java : Sélectionner tout modelColumn.setCellValueFactory(new PropertyValueFactory<>("model"));
Si la cellule est éditable et que son contenu est modifié, la propriété JavaFX de l'objet source sera directement mise à jour ; - si l'objet est accessible par une propriété Java Beans observable, nous pouvons l'empaqueter comme d'habitude grâce à un monteur prédéfini disponible dans le package javafx.beans.property.adapter :
Code Java : Sélectionner tout 1
2
3
4
5
6
7
8
9
10
11
12
13modelColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Car, String>, ObservableValue<String>>() { @Override public ObservableValue<String> call(TableColumn.CellDataFeatures<Car, String> param) { final Car car = param.getValue(); try { return JavaBeanStringPropertyBuilder.create().bean(car).name("model").build(); } catch (NoSuchMethodException ex) { Logger.getLogger(getClass().getName()).log(Level.SEVERE, ex.getMessage(), ex); return null; } } });
Ou :Code Java : Sélectionner tout 1
2
3
4
5
6
7
8
9modelColumn.setCellValueFactory(param -> { final Car car = param.getValue(); try { return JavaBeanStringPropertyBuilder.create().bean(car).name("model").build(); } catch (NoSuchMethodException ex) { Logger.getLogger(getClass().getName()).log(Level.SEVERE, ex.getMessage(), ex); return null; } });
Si la cellule est éditable et que son contenu est modifié, la propriété Java Beans observable de l'objet source sera directement mise à jour ; - Si l'objet n'est pas accessible par une propriété JavaFX ou une propriété Java Beans observable, nous allons devoir instancier manuellement une valeur observable pour stocker l'objet retourné :
Code Java : Sélectionner tout 1
2
3
4
5
6
7
8modelColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Car, String>, ObservableValue<String>>() { @Override public ObservableValue<String> call(TableColumn.CellDataFeatures<Car, String> param) { final Car car = param.getValue(); return new SimpleStringProperty(car.getModel()); } });
Ou :Code Java : Sélectionner tout 1
2
3
4modelColumn.setCellValueFactory(param -> { final Car car = param.getValue(); return new SimpleStringProperty(car.getModel()); });
Ici, il n'y a aucune liaison entre la propriété retournée et l'objet source, donc en cas d’édition les modifications ne sont pas reportées sur l'objet source.
Nous pouvons donc désormais peupler correctement notre table :
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 27 28 29 30 31 | final TableView<Car> tableView = new TableView(); tableView .getItems().setAll(car1, car2, car3, car4, car5); final TableColumn<Car, String> modelColumn = new TableColumn<>("Modèle"); modelColumn.setCellValueFactory(param -> { final Car car = param.getValue(); return new SimpleStringProperty(car.getModel()); }); final TableColumn<Car, String> brandColumn = new TableColumn<>("Marque"); brandColumn.setCellValueFactory(param -> { final Car car = param.getValue(); return new SimpleStringProperty(car.getBrand()); }); final TableColumn<Car, Color> colorColumn = new TableColumn<>("Couleur"); colorColumn.setCellValueFactory(param -> { final Car car = param.getValue(); return new SimpleObjectProperty<>(car.getColor()); }); final TableColumn<Car, Integer> seatsColumn = new TableColumn<>("Sièges"); seatsColumn.setCellValueFactory(param -> { final Car car = param.getValue(); return new SimpleObjectProperty<>(car.getSeats()); }); final TableColumn<Car, Integer> doorsColumn = new TableColumn<>("Portes"); doorsColumn.setCellValueFactory(param -> { final Car car = param.getValue(); return new SimpleObjectProperty<>(car.getDoors()); }); final TableColumn<Car, ?> optionsColumn = new TableColumn<>("Options"); optionsColumn.getColumns().setAll(colorColumn, seatsColumn, doorsColumn); tableView.getColumns().setAll(modelColumn, brandColumn, optionsColumn); tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); |
Ce qui nous donne :
Ici, chaque colonne de la table dispose de sa propre propriété cellFactory qui permet de placer un callback permettant de générer des cellules pour chaque ligne de cette colonne.
Prenons, par exemple, la couleur de la carrosserie de notre voiture. Nous allons utiliser une cellule qui affiche un rectangle de couleur (en fait une Region) :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class CarColorTableCell extends TableCell<Car, Color> { final Region region = new Region(); @Override protected void updateItem(Color item, boolean empty) { super.updateItem(item, empty); setGraphic(null); setText(null); if (!empty && item != null) { region.setBackground(new Background(new BackgroundFill(item, CornerRadii.EMPTY, Insets.EMPTY))); setGraphic(region); setContentDisplay(ContentDisplay.GRAPHIC_ONLY); } } } |
Et nous mettons cela en place sur la colonne en faisant :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 | colorColumn.setCellFactory(new Callback<TableColumn<Car, Color>, TableCell<Car, Color>>() { @Override public TableCell<Car, Color> call(TableColumn<Car, Color> tc) { return new CarColorTableCell(); } }); |
Ou :
Code Java : | Sélectionner tout |
colorColumn.setCellFactory(tc -> new CarColorTableCell());
Ce qui nous donne :
Il est possible d'activer l’édition sur une TableView en modifiant la valeur de sa propriété editable et en lui donnant la valeur true. De plus, chaque colonne dispose de sa propre propriété editable, ce qui permet d’activer ou de désactiver l’édition sur cette colonne.
Par exemple :
Code Java : | Sélectionner tout |
1 2 | tableView.setEditable(true); ageColumn.setEditable(false); |
Ici, bien que la table soit éditable, la colonne « Âge » ne l'est pas.
Elle deviendra éditable si nous faisons :
Code Java : | Sélectionner tout |
ageColumn.setEditable(true);
Cependant, les cellules utilisées par défaut dans l'affichage d'une TableView ne supportent pas le mode édition et donc rien ne se passera si l'utilisateur clique sur une valeur dans la table graphique.
Pour ajouter des cellules supportant le mode édition sur les colonnes, il est possible d'utiliser les cellules prêtes à l'emploi disponibles dans le package javafx.scene.control.cell. Bien qu'il soit possible de les étendre directement, ces classes disposent en général de méthodes de fabrique statiques pour en faciliter l'usage.
Par exemple, nous pouvons intégrer un éditeur dans la colonne affichant les prénoms :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | lastNameNameColumn.setCellFactory(TextFieldTableCell.forTableColumn()); firstNameColumn.setCellFactory(TextFieldTableCell.forTableColumn()); ageColumn.setCellFactory(TextFieldTableCell.forTableColumn(new StringConverter<Integer>() { @Override public String toString(Integer object) { return String.valueOf(object); } @Override public Integer fromString(String string) { return Integer.parseInt(string); } })); |
Ce qui nous donne :
Ici, par exemple, nous utilisons des éditeurs qui reposent sur des champs de saisie de texte. Désormais, lorsque l'utilisateur clique sur une valeur dans la table dans une de ces colonnes, un éditeur sera positionné à l'emplacement sélectionné. Étant donné que la colonne « Âge » contient des entiers et non pas des chaines de texte, nous devons donc passer un convertisseur en paramètre de la fabrique. Ce convertisseur permettra de transformer la saisie de l'utilisateur en entier de manière à changer l'âge et inversement.
Il est aussi possible de créer vos propres cellules éditeurs et de surcharger la méthode commitEdit().
Pour afficher des cases à cocher dans les colonnes contenant des valeurs booléennes, il faut utiliser des cellules prêtes à l'emploi de type javafx.scene.control.cell.CheckBoxTableCell. Vous pouvez soit directement étendre cette classe, soit utiliser une des méthodes statiques de fabrique disponibles.
Par exemple :
Code Java : | Sélectionner tout |
booleanColumn.setCellFactory(CheckBoxTableCell.forTableColumn(booleanColumn));
Note : si vous utilisez la fabrique statique, cette classe établit une liaison bidirectionnelle entre la propriété retournée par la fabrique à valeur et l’état selected de la case à cocher.
- si la valeur de la propriété change, l’état selected de la case à cocher sera mis à jour en conséquence ;
- si la table est éditable, sélectionner ou désélectionner la case mettra à jour la valeur de la propriété.
Pour afficher des boites déroulantes dans une TableView, il faut utiliser des cellules prêtes à l'emploi de type javafx.scene.control.cell.ChoiceBoxTableCell ou de type javafx.scene.control.cell.ComboBoxTableCell. Vous pouvez soit directement étendre ces classes, soit utiliser une des méthodes statiques de fabrique disponibles.
Par exemple :
Code Java : | Sélectionner tout |
sexColumn.setCellFactory(ChoiceBoxTableCell.forTableColumn(Person.Sex.values()));
Ce qui nous donne :
Ou :
Code Java : | Sélectionner tout |
sexColumn.setCellFactory(ComboBoxTableCell.forTableColumn(Person.Sex.values()));
Ce qui nous donne :
Dans les deux cas, une boite déroulante sera affichée lorsque la valeur passe en mode édition.
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 © 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.