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 :

TableView et une colonne CheckBox


Sujet :

JavaFX

  1. #1
    Membre du Club
    Inscrit en
    Janvier 2011
    Messages
    100
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 100
    Points : 50
    Points
    50
    Par défaut TableView et une colonne CheckBox
    Bonjour,

    J’ai un petit problème avec une TableView qui ne doit pas être compliqué à résoudre mais dont je ne trouve pas la solution sur le net !

    Je crée une TableView composée de 2 colonnes. La première est l’affichage du enum nommée Room (voir code ci-dessous) et la seconde une checkBox. L’affichage ne cause pas de problème mais je ne sais pas comment récupérer les données pour construire un objet Room (pas une enum dans ce cas-ci).

    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
     
    public enum Room {
        SCREAM("Scream"),
        CARRIE("Carrie");
     
        private String label;
     
        /**
         * Constructeur
         */
        Room(String label) {
            this.label = label;
        }
     
        public String getLabel() {
            return this.label;
        }
    }
    Je précise que je ne souhaite pas être 'informé' quand on coche une case de la ChecBox mais simplement savoir si un nom de chambre a été coché pour construire mon Objet Room.

    Afin de mieux comprendre, voici un peu de code :

    La construction de mon TableView :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
            data = FXCollections.observableArrayList(Room.values());
            table.setItems(data);
     
            final TableColumn<Room, String> roomCol = new TableColumn<>(Messages.getString("rooms"));
            roomCol.setCellValueFactory(new PropertyValueFactory("label"));
            roomCol.prefWidthProperty().bind(table.widthProperty().multiply(0.8));
            final TableColumn<Room, Boolean> checkCol = new TableColumn<>("Check");
            checkCol.setCellFactory(CheckBoxTableCell.forTableColumn(checkCol));
            checkCol.prefWidthProperty().bind(table.widthProperty().multiply(0.2));
            checkCol.setEditable(true);
            table.setEditable(true);
            table.getColumns().setAll(roomCol, checkCol);
    ... et la création de mon Objet Room :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
            Room room = new Room();
            cd.getRooms_TableView().getTable().getSelectionModel().  //ceci est un essai !
            room.setIdTeam(cd.getTfChipNbr().getText());
            room.setNameRoom(cd.getCbbNameRoom().getValue());  //Ceci sera supprimé. Je créais au départ une seule Room dont le nom était sélectionné dans une ComboBox
    J'imagine créer ma liste de Room en bouclant mon model de la TableView et vérifier si pour un nom d'une Room, la CheckBox est cochée.

    Merci pour votre attention.

    Marc

  2. #2
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Avec à la fois une enum et une classe qui s’appellent toutes les deux Room ça commence mal...
    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
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    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
    // Map: room -> propriété booléenne.
    final Map<Room, BooleanProperty> checkProperties = Arrays.stream(Room.values())
            .collect(Collectors.toMap(Function.identity(), room -> new SimpleBooleanProperty()));
    // Map: room -> listener.
    final Map<Room, ChangeListener<Boolean>> checkListeners = Arrays.stream(Room.values())
            .collect(Collectors.toMap(Function.identity(), room -> (observable, oldValue, newValue) -> {
                    System.out.printf("%s changed from %b to %b%n", room, oldValue, newValue);
                }));
    // Enregistrement listener.
    Arrays.stream(Room.values())
            .forEach(room -> {
                final BooleanProperty property = checkProperties.get(room);
                final ChangeListener<Boolean> listener = checkListeners.get(room);
                property.addListener(listener);
            });
    // Fabrique à cellule pour seconde colonne.
    checkCol.setCellValueFactory(feature -> {
        final Room room = feature.getValue();
        return checkProperties.get(room);
    });
    Note : ici j'ai fait 3 boucles pour bien découpler les étapes et rendre la chose plus compréhensible mais on peut faire avec moins.

    Note2 : stocker les listeners dans une map ça permet de les désenregistrer plus tard quand on démonte l'UI* et d'éviter ainsi une fuite mémoire.

    *Oui je sais personne ne le fait jamais d'où les plantages mémoire des apps Java
    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

  4. #4
    Membre à l'essai
    Homme Profil pro
    Fonctionnaire
    Inscrit en
    Août 2016
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Fonctionnaire
    Secteur : Finance

    Informations forums :
    Inscription : Août 2016
    Messages : 28
    Points : 14
    Points
    14
    Par défaut
    Bonjour et merci.

    Oui, effectivement Room et Room, c'est pour se perdre. Et donc, j'ai intitulé mon enum EnumRoom ...

    Je dois avouer que je suis un peu perdu dans ton code
    Je ne m'attendais pas à devoir faire ça pour construire mon Objet Room.

    Et donc, cette question : à quel endroit je construis mon Objet ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    ObservableList<Room> rooms = FXCollections.observableArrayList();
     
    //début d'une boucle ###############
    // * c'est ici qu'intervient ton code ... --> Dans le TableView, si la CheckBox est cochée face à un nom de Room, je crée ma Room
    if(*){
      Room room = new Room;
      room.setIdTeam(cd.getTfChipNbr().getText());
      room.setNameRoom(cd.getCbbNameRoom().getValue());  
      rooms.add(room);
    }
    //fin de la boucle ##################
     
    t.setRooms(room);  // t étant un Objet 'Team' qui contient une liste de 'Room'
    Oui, effectivement, je n'ai pas utilisé les stream dans mon code mais je ne suis pas à l'aise avec ça !!!

  5. #5
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Pour chaque objet de EnumRoom (autant utiliser les nouveau noms) mon code crée une BooleanProperty et met un listener dessus. Ce listener permet de savoir quand la valeur de la propriété change, c'est a dire quand l'utilisateur coche ou décoche la check box dans la table. Donc lorsque dans mon code il se déroule System.out.printf("%s changed from %b to %b%n", room, oldValue, newValue);, ca veut dire que pour cette EnumRoom, la case a été cochée ou décochée... donc tu peux agir en conséquence...

    Tout ce code est nécessaire car tu te contentes de mettre des EnumRoom directement dans ta TableView. Ça aurait été bien plus simple si tu avais créé un objet composite servant de modèle pour la table :

    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
    public class Main extends Application {
     
        @Override
        public void start(final Stage primaryStage) throws Exception {
            final TableView<RoomTableModel> table = new TableView<>();
            final RoomTableModel[] model = Arrays.stream(EnumRoom.values())
                    .map(RoomTableModel::new)
                    .toArray(RoomTableModel[]::new);
            Arrays.stream(model)
                    .forEach(modelItem -> modelItem.checkedProperty().addListener((observable, oldValue, newValue) -> System.out.printf("%s changed from %b to %b%n", modelItem.getEnumRoom(), oldValue, newValue)));
            table.getItems().setAll(model);
            final TableColumn<RoomTableModel, String> roomCol = new TableColumn<>("Rooms");
            roomCol.setCellValueFactory(new PropertyValueFactory("label"));
            roomCol.prefWidthProperty().bind(table.widthProperty().multiply(0.8));
            final TableColumn<RoomTableModel, Boolean> checkCol = new TableColumn<>("Check");
            checkCol.setCellValueFactory(new PropertyValueFactory("checked"));
            checkCol.setCellFactory(CheckBoxTableCell.forTableColumn(checkCol));
            checkCol.prefWidthProperty().bind(table.widthProperty().multiply(0.2));
            checkCol.setEditable(true);
            table.setEditable(true);
            table.getColumns().setAll(roomCol, checkCol);
            final AnchorPane root = new AnchorPane(table);
            final Scene scene = new Scene(root);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
     
        public static void main(String... args) {
            Application.launch(args);
        }
     
        public static final class RoomTableModel {
     
            private final EnumRoom enumRoom;
     
            public RoomTableModel(final EnumRoom enumRoom) {
                this.enumRoom = enumRoom;
            }
     
            public final EnumRoom getEnumRoom() {
                return enumRoom;
            }
     
            public final String getLabel() {
                return enumRoom.getLabel();
            }
     
            private final BooleanProperty checked = new SimpleBooleanProperty(this, "checked");
     
            public final boolean isChecked() {
                return checked.get();
            }
     
            public void setChecked(final boolean value) {
                checked.set(value);
            }
     
            public final BooleanProperty checkedProperty() {
                return checked;
            }
        }
    }
    Ici la classe modèle est publique car PropertyValueFactory utilise l'introspection pour accéder aux propriétés. Je ne l'ai pas fait ici mais comme dans le code précédent, il faudrait conserver une référence sur les listeners pour pouvoir les désenregistrer quand on en a plus besoin.
    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

  6. #6
    Membre du Club
    Inscrit en
    Janvier 2011
    Messages
    100
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 100
    Points : 50
    Points
    50
    Par défaut
    OK, super, c'est plus clair.

    J'ai pu faire ce que je voulais. Je n'ai pas utilisé de listener car je ne voulais pas cette solution.

    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
     
    // Map: room -> propriété booléenne.
    checkProperties = Arrays.stream(EnumRoom.values())
            .collect(Collectors.toMap(Function.identity(), room -> new SimpleBooleanProperty()));
     
    // Fabrique à cellule pour seconde colonne.
    checkCol.setCellValueFactory(feature -> {
            final EnumRoom room = feature.getValue();
            return checkProperties.get(room);
    });
     
    ObservableList<Room> rooms = FXCollections.observableArrayList();
    checkProperties.forEach((k, v)-> {
                if(v.getValue().equals(true)){
                    final Room room = new Room();
                    room.setIdTeam(ntd.getTfChipNbr().getText());
                    room.setNameRoom(k.getLabel());
                    rooms.add(room);
                }
    });
    J'aurais une dernière question. J'aurais souhaité savoir si au moins une des CheckBox était cochée (car au moins une DOIT être cochée). Et donc, j'ai pensé à ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    if(!checkProperties.containsValue(true)){
    ...
    }
    ...mais ça ne fonctionne pas ! Une idée ?

    Marc

  7. #7
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Du coup, sans binding ou gestion des évènements, je ne vois pas trop comment tu peux savoir que les cases sont cochées ou pas en fonction des actions de l'utilisateur.

    Pour l'autre soucis, checkProperties est une Map<EnumRoom, BooleanProperty> comment tu peux espérer trouver la valeur true dedans ?

    Un truc du genre devrait probablement faire un peu mieux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    boolean somethingIsChecked = checkProperties.valueSet()
       .stream()
       .filter(BooleanProperty::get)
       .findFirst()
       .isPresent();
    Mais bon... ça ne te donne l’état des checkbox qu'au moment ou tu lances cette recherche.
    Ce n'est pas vraiment ce qu'il faut faire lorsque tu as des propriétés... où tu dois réagir lors des changements d’états (d’où le binding ou les évènements).
    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

  8. #8
    Membre du Club
    Inscrit en
    Janvier 2011
    Messages
    100
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 100
    Points : 50
    Points
    50
    Par défaut
    Bonjour,

    Oui effectivement, je n'utilise pas de gestionnaire d’événement mais je l'avais précisé dans ma demande (Je précise que je ne souhaite pas être 'informé' quand on coche une case de la ChecBox...).

    Pour ta solution qui permet de vérifier si au moins une case est cochée, elle me convient, c'est parfait pour moi.

    Encore merci pour toute cette aide.

    Marc

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 01/09/2008, 15h56
  2. Jvcl(grid avec une colonne checkbox)
    Par Klemsy78 dans le forum Delphi
    Réponses: 2
    Dernier message: 02/11/2006, 21h15
  3. [CF][PPC/VB.NET/Datagrid] Comment gérer une colonne CheckBox ?
    Par joefou dans le forum Windows Mobile
    Réponses: 5
    Dernier message: 28/08/2006, 17h08
  4. Réponses: 3
    Dernier message: 26/07/2006, 10h18
  5. Réponses: 2
    Dernier message: 19/05/2006, 18h01

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