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

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaFX Discussion :

Déroulement d'un listView élément par élément


Sujet :

JavaFX

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    876
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 876
    Par défaut Déroulement d'un listView élément par élément
    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 :

    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 »
    Je devrais voir :

    Titre : A
    ----Sous-titre : K
    ------------Valeur : un
    ------------Valeur : deux
    ----Sous-titre : L
    ------------Valeur : trois
    Titre : B
    ----Sous-titre : M
    ------------Valeur : quatre
    Ca j’arrive à faire avec un ListView, un VBox et quelques HBox comme vous le verrez dans le code ci-dessous...
    Nom : ListView.PNG
Affichages : 1082
Taille : 4,5 Ko


    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 :

    Titre : A
    ----Sous-titre : K
    ------------Valeur : un
    ------------Valeur : deux
    ----Sous-titre : L
    ------------Valeur : trois
    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 »).
    Mon nouvel affichage de 6 lignes ne sera PAS :

    ----Sous-titre : K
    ------------Valeur : un
    ------------Valeur : deux
    ----Sous-titre : L
    ------------Valeur : trois
    Titre : B
    Mais devrait être (pour respecter la règle ci-avant)

    Titre : A
    ----Sous-titre : K
    ------------Valeur : deux
    ----Sous-titre : L
    ------------Valeur : trois
    Titre : B

    EBAUCHE DE SOLUTION


    J’ai créé une classe :


    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;
        }
     
     
    }
    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.

    Lorsque je remplis mon observablelist, je peux remplir correctement ces deux boolean.


    Je peux donc créer une observablelist comme ceci :

    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)
    			);
    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
    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);
     
                            }
                        }
     
                    };
                }
     
            });
    Et quel est le problème alors ??

    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.

  2. #2
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 904
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 904
    Billets dans le blog
    54
    Par défaut
    A première vue, je dirais que ce n'est pas possible dans le ListView par défaut (ou plutôt dans son skin par défaut). Et donc du coup, je pense que le problème est surtout gérable en créant un nouveau skin pour ce contrôle mais cela va demander pas mal de trucs a coder (rappel les skins par défaut devraient être publiques dans le JDK9, actuellement ils ne le sont pas donc il faut se reposer sur les sources disponibles via l'OpenJFX). Ou alors créer ton propre composant qui étend Region et inclue et gère manuellement sa propre barre de défilement et sa propre représentation du contenu (via quelques chose de similaire aux cellules ou plus simple).

    Le but dans les deux cas de faire que lors d'une opération de défilement, on se retrouve toujours avec un composant qui est callé sur le bord haut de la liste de manière a toujours le voir en mode "expanded".
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    876
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 876
    Par défaut
    Bonjour,

    MERCI d'avoir pris le temps de comprendre la problématique.

    Je ne vais évidemment pas me lancer dans la création des Skins, d'autant plus que je suis contraint à utiliser le JDK 1.7.

    Je pense que dès lors la création d'un composant sur mesure va s'imposer. Tu l'as bien compris, la difficulté est que les différents éléments de ma liste ont une hauteur différente (de 1 à 3 lignes) et qu'un élément en première position doit toujours afficher les 3 lignes, même si placé ailleurs dans la liste il n'en comprend que une ou deux.

    J'ai deux pistes:

    La première serait d'utiliser un listView dans lequel je contrôlerait le nombre d'éléments pour que le scroll vertical ne s'affiche jamais. j'aurais donc une petite Observable collection qui correspondrait aux éléments que je veux afficher. J'aurais un bouton "bas" et un bouton "haut" qui ferait office de curseur. Chaque fois que j'utiliserais le bouton bas, il m'effacerait l'item(0) de mon Observable collection et me rajouterait un élément en fin de liste. J'ai déjà testé ce principe qui m'a amené un nouveau problème que j'ai exprimé dans une discussion séparée. Je marque donc celle-ci comme résolue.

    La deuxième serait basée sur le même principe que la précédente, mais pour avoir encore plus de contrôle sur les éléments affichés, j'utiliserais un VBOX pour gérer ma liste d'éléments et un VBOX pour gérer les 3 lignes de chaque élément. Mais ça ce sera pour le prochain épisode.

    Merci encore pour ton aide

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [CR 8] Split d'un champ élément par élément
    Par mscpleaz dans le forum Formules
    Réponses: 2
    Dernier message: 19/06/2015, 10h19
  2. Remplir un tableau élément par élément
    Par Piroh dans le forum Pascal
    Réponses: 4
    Dernier message: 10/02/2015, 15h23
  3. Faire des opérations élément par élément
    Par fahimonasri dans le forum MATLAB
    Réponses: 2
    Dernier message: 25/11/2013, 15h06
  4. [CSV] Parcourir un CSV élément par élément
    Par malvax dans le forum Langage
    Réponses: 2
    Dernier message: 15/03/2009, 23h44
  5. [Dates] pb pour afficher éléments par éléments
    Par linouline dans le forum Langage
    Réponses: 9
    Dernier message: 04/06/2006, 14h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo