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 mise à jour d'une seule cellule


Sujet :

JavaFX

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Janvier 2011
    Messages
    100
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 100
    Par défaut TableView mise à jour d'une seule cellule
    Bonjour,

    J’ai une TableView composée de 2 colonnes. La première est l’affichage du enum (EnumRoom) nommée roomCol (affiche le nom des chambres). La seconde, un String (qui correspond à l’état d’une chambre -> String "inoccupée" ou si elle est occupée, affiche le nom de la personne qui l’occupe) nommée stateRoomsCol.
    Voici un bout de code :
    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
     
    // Map<EnumRoom, StringProperty> mapRooms;
    data = FXCollections.observableArrayList(EnumRoom.values());
    table.setItems(data);
    //mapRooms = Arrays.stream(EnumRoom.values())
    //          .collect(Collectors.toMap(Function.identity(), nameTeam -> new SimpleStringProperty()));
    final TableColumn<EnumRoom, String> roomCol = new TableColumn<>("Nom chambre");
    roomCol.setCellValueFactory(new PropertyValueFactory("label"));
    final TableColumn<EnumRoom, String> stateRoomsCol = new TableColumn<>("Nom personne");
    //stateRoomsCol.setCellValueFactory(feature -> {
     //           final EnumRoom room = feature.getValue();
    //            if(team!=null&&nameRoom.equalsIgnoreCase(room.getLabel())){
    //                return mapRooms.get(nameRoom);
    //            }else{
    //                return new SimpleStringProperty("inoccupée");
    //            }
    //        });
    Via la technologie RMI, je souhaite modifier une seule cellule du TableView (c-à-d l’état de la chambre -> passer de l’état : inoccupée à l’état : nom de la personne qui occupe la chambre) à l’aide d’une méthode appelée par exemple updateCellRoom (via client RMI).

    Mon problème n’est pas la technologie RMI mais c'est que je ne parviens pas à modifier la cellule qui représente l’état de la chambre.
    Dans le code qui précède, j'ai essayé en utilisant une Map (code en commentère) mais je n'ai pas su résoudre le problème.

    La méthode updateCellRoom 'contiendrait' le nouvel état de la chambre (nom de la personne qui occupe la chambre) et le nom de la chambre en question. Et donc, ce que je souhaite c’est d'adapter la cellule de la colonne stateRoomsCol qui correspond au nom de la chambre (nom de l'enum qui correspond au nom que la méthode updateCellRoom 'contient') -> colonne roomCol. Tout ceci sans modifier l'état des autres cellules de la colonne stateRoomsCol.

    J'espère que j'ai pu me faire comprendre

    Si quelqu'un peut m'aider ... Merci de 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 899
    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 899
    Billets dans le blog
    54
    Par défaut
    La table se met à jour toute seule lorsque la propriété change.

    Comment as-tu codé ta propriété : est-elle observable ? Est-elle une propriété JavaFX ? Est-elle une propriété observable Java Beans ? Est-ce que c'est juste un getter ?
    Si c'est la solution 3, il n'y aura pas de mise à jour car un simple getter ce n'est pas observable (la table ne peut pas être au courant des modifs car ces dernières ne remontent jamais jusqu'à l'UI).
    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 confirmé
    Inscrit en
    Janvier 2011
    Messages
    100
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 100
    Par défaut
    Le problème c'est que la colonne roomCol, qui contient une enum, n'a rien avoir avec la valeur de la colonne stateRoomsCol qui est au départ un simple String et ensuite (grâce à la méthode updateCellRoom -> RMI) est le nom d'un client (classe Person). Donc, j'imagine qu'il n'y a pas vraiment de solution !

  4. #4
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 899
    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 899
    Billets dans le blog
    54
    Par défaut
    Je ne vois pas le rapport. Comment as-tu codé le modèle de la table (ou du moins de cette colonne) ?
    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

  5. #5
    Membre confirmé
    Inscrit en
    Janvier 2011
    Messages
    100
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 100
    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
     
    data = FXCollections.observableArrayList(EnumRoom.values());
    table.setItems(data);
     
    final TableColumn<EnumRoom, String> roomCol = new TableColumn<>("Nom chambre");
    roomCol.setCellValueFactory(new PropertyValueFactory("label"));
     
    final TableColumn<EnumRoom, String> stateRoomsCol = new TableColumn<>("Nom personne");
            stateRoomsCol.setCellValueFactory(feature -> {
                final EnumRoom room = feature.getValue();
                if(team!=null&&nameRoom.equalsIgnoreCase(room.getLabel())){
                    return mapRooms.get(nameRoom);
                }else{
                    return new SimpleStringProperty("inoccupée");
                }
            });
     
    table.getColumns().setAll(roomCol, stateRoomsCol);
    Mais ça ne me convient pas !

    J'en profite pour me pencher aussi sur ton affirmation : "La table se met à jour toute seule lorsque la propriété change."
    Je ne procède pas de la bonne manière certainement car si j'ai bien une 'ObservableList', ma TableView ne se met pas à jour automatiquement quand mon 'ObservableList' est modifiée. Je dois mettre à jour ma TableView à l'aide du pattern Observer !

  6. #6
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 899
    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 899
    Billets dans le blog
    54
    Par défaut
    Non ! le parttern observer est deja utilise partout ou tu as des trucs observables (listes observables, propriétés observables, évènements claviers, souris, etc.............................................)

    On reprend car ce n'est pas clair pour tout le monde (ENCORE ) :

    1. Une table, en JavaFX, c'est : une liste d'objets observables. Tu veux changer les objets dans la table -> tu changes le contenu de la liste -> Ça changera tout le contenu de toutes les cellules de toutes les lignes et de toutes les colonnes.
    2. Les colonnes de la table, en JavaFX : la colonne X c'est une vue sur une propriété d'un objet situé dans la liste observable de la table a la ligne Y. Tu veux changer ce qui est affiche dans la cellule -> tu changes la valeur de la propriété dans l'objet. Si elle est observable -> automatiquement, via le pattern observer, la cellule (X, Y) va afficher la nouvelle valeur. Les autres cellules (meme celles affichant une autre vue / propriété de l'objet sur la ligne Y) ne sont pas impactées.



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    stateRoomsCol.setCellValueFactory(feature -> {
        final EnumRoom room = feature.getValue();
        if(team!=null&&nameRoom.equalsIgnoreCase(room.getLabel())){
            return mapRooms.get(nameRoom);
        }else{
            return new SimpleStringProperty("inoccupée");
        }
    }
    Ici, a la ligne 4 je ne sais pas ce que contient mapRooms mais tu renvoie une ObservableValue<MachinChose>. Si le MachinChose contenu dans cette valeur observable change, la cellule changera de contenu.
    Par contre la ligne 6 tu renvoie une propriete créée localement totalement découplée de tout. Comment tu veux que la table soit au courant que la valeur peut changer après ?

    Pourquoi ne pas toujours renvoyer mapRooms.get(nameRoom) et faire que quand ça contient null ou la valeur d'enum EMPTY/VACANT/etc... alors ta cellule affiche inoccupée ? Apres tout tu semble ici en voulant retourner une String vouloir faire le boulot de la cellule plutot que de la valeur. Tu sembles donc ne pas faire la distinction entre l'extraction de la donnee pertinente et l'affichage "joli" pour l'utilisateur humain.

    cellValueFactory -> prend une chambre et renvoie un objet observable contenant la valeur appropriée pour la colonne -> ici une ObservableValue<WhateverEnum> indiquant l’état d'occupation de la chambre
    cellFactory -> prend une valeur d’état d'occupation (WhateverEnum) et affiche la bonne chaine de caractères / icone / couleur / decoration / etc. en fonction.


    C'est pas bien complique pourtant de se faire un petit prog de test :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    package hotelresa;
     
    public enum RoomAvailability {
        EMPTY, BOOKED, OCCUPIED;
    }
    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
    package hotelresa;
     
    import javafx.beans.property.ObjectProperty;
    import javafx.beans.property.SimpleObjectProperty;
     
    public final class Room {
     
        private final ObjectProperty<RoomAvailability> availability = new SimpleObjectProperty<>(this, "availability", RoomAvailability.EMPTY);
     
        public RoomAvailability getAvailability() {
            return availability.get();
        }
     
        public void setAvailability(RoomAvailability value) {
            availability.set(value);
        }
     
        public ObjectProperty availabilityProperty() {
            return availability;
        }
    }
    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
    87
    88
    89
    package hotelresa;
     
    import java.util.Arrays;
    import java.util.stream.IntStream;
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.TableCell;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableView;
    import javafx.scene.control.ToolBar;
    import javafx.scene.control.cell.PropertyValueFactory;
    import javafx.scene.layout.BorderPane;
    import javafx.stage.Stage;
     
    public class Main extends Application {
     
        @Override
        public void start(final Stage primaryStage) throws Exception {
            final TableColumn<Room, RoomAvailability> stateColumn = new TableColumn<>("State");
            // Extraction
            stateColumn.setCellValueFactory(new PropertyValueFactory<>("availability"));
            // Affichage
            stateColumn.setCellFactory(tableColumn -> new TableCell<Room, RoomAvailability>() {
                @Override
                protected void updateItem(RoomAvailability item, boolean empty) {
                    super.updateItem(item, empty);
                    String text = null;
                    String style = null;
                    if (!empty && item != null) {
                        switch (item) {
                            case BOOKED: {
                                text = "Réservée";
                                style = "-fx-text-fill: gold;";
                            }
                            break;
                            case EMPTY: {
                                text = "Inoccupée";
                                style = "-fx-text-fill: lightgray;";
                            }
                            break;
                            case OCCUPIED: {
                                text = "Occupée";
                                style = "-fx-font-weight: bold;";
                            }
                            break;
                        }
                    }
                    setText(text);
                    setStyle(style);
                }
            });
            final TableView<Room> tableView = new TableView<>();
            tableView.getColumns().add(stateColumn);
            tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
            //
            final RoomAvailability[] states = RoomAvailability.values();
            final int roomNumber = 10;
            final Room[] model = IntStream.range(0, roomNumber)
                    .mapToObj(index -> {
                        final int stateIndex = (int) (states.length * Math.random());
                        final RoomAvailability state = states[stateIndex];
                        final Room room = new Room();
                        room.setAvailability(state);
                        return room;
                    })
                    .toArray(Room[]::new);
            tableView.getItems().setAll(model);
            //
            final Button testButton = new Button("Free all rooms");
            // Comme tout est observable, le changement de valeur est automatiquement reporte sur la table !!!!!!!!!!!!!!!!!!! On a rien besoin de faire !!
            testButton.setOnAction(actionEvent -> Arrays.stream(model)
                    .forEach(room -> room.setAvailability(RoomAvailability.EMPTY)));
            //
            final ToolBar toolBar = new ToolBar();
            toolBar.getItems().add(testButton);
            //
            final BorderPane root = new BorderPane();
            root.setCenter(tableView);
            root.setTop(toolBar);
            final Scene scene = new Scene(root);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
     
        public static void main(String... args) {
            Application.launch(args);
        }
    }
    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

Discussions similaires

  1. Mise à jour d'une seule colonne depuis une table existante
    Par marc73450 dans le forum Requêtes
    Réponses: 4
    Dernier message: 29/04/2013, 11h14
  2. Réponses: 3
    Dernier message: 22/10/2008, 21h00
  3. Réponses: 3
    Dernier message: 06/12/2007, 11h09
  4. Lancement d'une macro après mise à jour d'une cellule
    Par Mukade dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 17/10/2007, 11h52
  5. Réponses: 6
    Dernier message: 03/10/2006, 09h44

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