Bonjour,
Voici un beau challenge pour ceux qui savent et que ça intéresse...
LE PROBLEME :
Je dois afficher une liste d’éléments d’une manière bien précise.
Chaque élément comprend un Titre, un sous-titre et un contenu.
LA REGLE :
Le premier élément que j’affiche doit toujours montrer (disposé l’un en dessous de l’autre) :
Le Titre
Le Sous-titre
Le contenu
Les éléments suivants que j’affiche doivent montrer :
Le Titre (mais seulement s’il est différent de celui de l’élément juste avant )
Le Sous-titre (mais seulement s’il est différent de celui de l’élément juste avant )
Le contenu (dans tous les cas)
EXEMPLE :
Imaginons que j’aie 4 éléments à afficher :
Je devrais voir :Titre = « A »
Sous-titre = « K »
Contenu = « un »
Titre = « A »
Sous-titre = « K »
Contenu = « deux »
Titre = « A »
Sous-titre = « L »
Contenu = « trois »
Titre = « B »
Sous-titre = « M »
Contenu = « Quatre »
Ca j’arrive à faire avec un ListView, un VBox et quelques HBox comme vous le verrez dans le code ci-dessous...Titre : A
----Sous-titre : K
------------Valeur : un
------------Valeur : deux
----Sous-titre : L
------------Valeur : trois
Titre : B
----Sous-titre : M
------------Valeur : quatre
On voit bien par l'alternance des couleurs que certains Items (comme le 1er et le 4ème) font trois lignes, que le deuxième Item ne fait qu'une ligne car le titre et le sous-titre sont cachés et enfin que le troisième Item fait 2 lignes.
Il faut évidemment imaginer que ma liste contient bien plus que 4 éléments et que je dois pouvoir scroller plus bas dans ma liste.
Imaginons pour l’example que mon ListView puisse n’afficher que 6 lignes. A l’ouverture on verrait :
Mais si à ce moment je click sur le bouton « bas » de ma barre de scroll, ça veut dire que je veux voir l’élément suivant (dans mon exemple, le quatrième élément) et aussi que mon premier élément va disparaitre (celui qui a la valeur « un »).Titre : A
----Sous-titre : K
------------Valeur : un
------------Valeur : deux
----Sous-titre : L
------------Valeur : trois
Mon nouvel affichage de 6 lignes ne sera PAS :
Mais devrait être (pour respecter la règle ci-avant)----Sous-titre : K
------------Valeur : un
------------Valeur : deux
----Sous-titre : L
------------Valeur : trois
Titre : B
Titre : A
----Sous-titre : K
------------Valeur : deux
----Sous-titre : L
------------Valeur : trois
Titre : B
EBAUCHE DE SOLUTION
J’ai créé une classe :
Vous constaterez qu’en plus de titre 1 et titre 2 (sous-titre), j’ai deux boolean qui m’indiquent au niveau de l’élément si le titre ou le sous-titre est différent de celui de l’élément précédent.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public class ListElement { private final StringProperty titre1; private final StringProperty titre2; private final StringProperty valeur; private final BooleanProperty siPremierTitre1; private final BooleanProperty siPremierTitre2; /** * Default constructor. */ public ListElement(String t1, String t2, String v , Boolean sit1,Boolean sit2 ) { this.titre1 = new SimpleStringProperty(t1); this.titre2 =new SimpleStringProperty(t2); this.valeur = new SimpleStringProperty(v); this.siPremierTitre1 = new SimpleBooleanProperty(sit1) ; this.siPremierTitre2 = new SimpleBooleanProperty(sit2) ; } public String getTitre1() { return titre1.get(); } public void setTitre1(String titre1) { this.titre1.set(titre1); } public StringProperty titre1Property() { return titre1; } public String getTitre2() { return titre2.get(); } public void setTitre2(String titre2) { this.titre2.set(titre2); } public StringProperty titre2Property() { return titre2; } public String getValeur() { return valeur.get(); } public void setValeur(String valeur) { this. valeur.set( valeur); } public StringProperty valeurProperty() { return valeur; } public Boolean getSiPremierTitre1() { return siPremierTitre1.get(); } public void setSiPremierTitre1(Boolean siPremierTitre1) { this. siPremierTitre1.set( siPremierTitre1); } public BooleanProperty siPremierTitre1Property() { return siPremierTitre1; } public Boolean getSiPremierTitre2() { return siPremierTitre2.get(); } public void setSiPremierTitre2(Boolean siPremierTitre2) { this. siPremierTitre2.set( siPremierTitre2); } public BooleanProperty siPremierTitre2Property() { return siPremierTitre2; } }
Lorsque je remplis mon observablelist, je peux remplir correctement ces deux boolean.
Je peux donc créer une observablelist comme ceci :
Enfin j’arrive à formater ma liste exactement comme je veux avec :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 ObservableList<ListElement> myObservableListEL = FXCollections.observableArrayList( new ListElement("A", "K", "1",true, true), // nouveau titre, nouveau sous-titre new ListElement("A", "K", "2",false, false), //même titre et même sous-titre que lélément précédent new ListElement("A", "L", "3",false, true), // nouveau sous titre new ListElement("B", "M", "4",true, true), // nouveau titre, nouveau sous-titre new ListElement("B", "M", "5",false, false) );
Et quel est le problème alors ??
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
32
33
34
35
36
37
38
39 lvObj.setCellFactory(new Callback<ListView<ListElement>, ListCell<ListElement>>() { @Override public ListCell<ListElement> call(ListView<ListElement> arg0) { return new ListCell<ListElement>() { @Override protected void updateItem(ListElement item, boolean bln) { super.updateItem(item, bln); if (item != null) { VBox vBox = new VBox(); if(item.getSiPremierTitre1()) //ici je ne teste que si getSiPremierTitre1 est vrai, mais je devrais aussi afficher le titre si c'est le premier item de mon ListView { HBox hBox = new HBox(); hBox.getChildren().addAll(new Label("Titre 1 "), new Text(item.getTitre1())); vBox.getChildren().addAll(hBox); } if(item.getSiPremierTitre2())//ici je ne teste que si getSiPremierTitre2 (sous-titre) est vrai, mais je devrais aussi afficher le sous-titre si c'est le premier item de mon ListView { HBox hBox = new HBox(); hBox.getChildren().addAll(new Label(" Titre 2 "), new Text(item.getTitre2())); vBox.getChildren().addAll(hBox); } HBox hBox = new HBox(); hBox.getChildren().addAll(new Label(" Ma valeur = "), new Text(item.getValeur())); // ma valeur, je l'affiche toujours vBox.getChildren().addAll(hBox); setGraphic(vBox); } } }; } });
Ben c’est que ma liste ne s’affiche comme je veux qu’à l’ouverture du listView.
Dès que je déroule vers le bas j’ai ma listeView qui remonte demi-ligne par demi ligne et ce n’est plus un élément complet (titre, sous-titre et contenu) qui est visible en première position.
Moi je voudrais que ce soit toujours un élément complet qui s’affiche en première position.
Y-a-t-il donc une « option » pour qu’il n’affiche seulement qu’un élément complet au-dessus de mon listView ?
Et aussi qu’à chaque fois que mon élément change en première position, le setCellFactory pour cet élément soit appelé (pour que le titre et le sous-titre s’affichent.
Voilà, j’espère avoir été clair...
Merci d’avance pour qui pourra m’aider.
Partager