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 éditable: impossible de garder la liste de départ


Sujet :

JavaFX

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2014
    Messages
    101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2014
    Messages : 101
    Points : 71
    Points
    71
    Par défaut Tableview éditable: impossible de garder la liste de départ
    Bonsoir,

    Voilà, je suis un peu perdu. Je crée une tableview éditable et je récupère une liste d'items dans une base de données. Avant de charger la liste dans la tableview, je fais une copie de la liste dans une autre liste pour garder les valeurs de départ. Néanmoins, quand la liste est chargée et qu'une modification est effectuée au sein d'une cellule (les cellules d'une ligne sont respectivement une TextFieldTableCell et une ComboBoxTableCell), ce sont les deux listes qui sont mises à jour... Aussi, je perds les valeurs de départ que je souhaitais garder dans la liste où je les avais copiées après récupération de la liste principale.
    Par hasard, quelqu'un aurait-il une idée sur comment je pourrais résoudre ce problème ?

    Je vous en remercie d'avance et vous souhaite une bonne soirée.

    Cordialement,

    Vincent

  2. #2
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut
    sans code, on ne peut pas t'aider. je te propose de poster un peu de ton code pour qu'on puisse comprendre mieux ton problème.

  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
    Que contient ta liste ? Des objets ? Des valeurs simples (strings, nombres) ? Qu'est ce que tu édites dans ta table (des champs de l'objet, des propriétés FX ou Bean, des valeurs simples) ? Comment effectues-tu ta copie ? Clones-tu tes objets ?
    Pas de code, pas de solution.
    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 régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2014
    Messages
    101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2014
    Messages : 101
    Points : 71
    Points
    71
    Par défaut
    Bonsoir,

    J'ai reproduit le cas sur un exemple personnel. Au niveau du controller, le voilà ci-dessous:

    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
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
     
    public class RootController implements Initializable{
     
    	@FXML 
    	private TextField userTfd;
    	@FXML 
    	private TableView<User> userTbv;
    	@FXML 
    	private TableColumn<User, String> userNomCol;
    	@FXML 
    	private TableColumn<User, String> metierCol;
    	@FXML 
    	private GridPane gp;
    	@FXML 
    	private GridPane ssGp;
    	@FXML 
    	private Button ajoutBtn;
    	@FXML 
    	private Button modifBtn;
    	@FXML 
    	private Button enregistrerBtn;
     
    	private ObservableList<String> metiers;
    	@FXML 
    	private TextField nomTfd;
    	@FXML 
    	private ComboBox<String> metierCb;
    	@FXML
    	private List<User> initialList;
    	@FXML Button annulerBtn;
    	@Override
    	public void initialize(URL arg0, ResourceBundle arg1) {
    		initMetiers();
    		initTabView();
    		initMetierCb();
    		initUsers();
    		List<User> userls = new java.util.ArrayList<User>();
    		userls.addAll(initialList);
    		userTbv.getItems().addAll(userls);
    	}
     
    	public void initMetierCb(){
    		metierCb.setItems(metiers);
    	}
     
     
     
    	public void initTabView() {
            userNomCol.setCellValueFactory(e -> new SimpleStringProperty(e.getValue().getNom()));
            metierCol.setCellValueFactory(e -> new SimpleStringProperty(e.getValue().getMetier()));
            userNomCol.setCellFactory(TextFieldTableCell.forTableColumn(new DefaultStringConverter()));
            metierCol.setCellFactory(ComboBoxTableCell.forTableColumn(metiers));
            userTbv.setEditable(true);
            userNomCol.setEditable(true);
     
            userNomCol.setOnEditCommit(new EventHandler<CellEditEvent<User, String>>() {
                @Override
                public void handle(CellEditEvent<User, String> t) {
                    User ag = t.getTableView().getItems().get(t.getTablePosition().getRow());
                    if (t.getNewValue() != null && !((t.getNewValue()).replaceAll("\\s", "")).equals("")) {
                        ag.setNom(t.getNewValue());
                    } else {
                        ag.setNom(t.getOldValue());
                        t.getTableView().getColumns().get(0).setVisible(false);
                        t.getTableView().getColumns().get(0).setVisible(true);
                    }
                }
            });
     
            metierCol.setOnEditCommit(new EventHandler<CellEditEvent<User, String>>() {
                @Override
                public void handle(CellEditEvent<User, String> t) {
                    ((User) t.getTableView().getItems().get(t.getTablePosition().getRow())).setMetier(t.getNewValue());
                }
            });
     
        }
     
     
    	public void initMetiers(){
    		metiers = FXCollections.observableArrayList("métier 1","métier 2","métier 3","métier 4","métier 5","métier 6");
    	}
     
    	public void initUsers(){
    		User user1 = new User();
    		user1.setNom("Albert");
    		user1.setMetier("métier1");
    		User user2 = new User();
    		user2.setNom("Louis");
    		user2.setMetier("métier3");
    		User user3 = new User();
    		user3.setNom("Marion");
    		user3.setMetier("métier5");
    		initialList = FXCollections.observableArrayList(user1, user2, user3);
     
    	}
     
     
    	@FXML public void ajouterUser(ActionEvent event) {
    		User user = new User();
    		user.setNom(nomTfd.getText());
    		user.setMetier(metierCb.getValue());
    		userTbv.getItems().add(user);
    		nomTfd.setText("");
    		metierCb.setValue("");
     
    	}
     
     
     
    	@FXML public void enregistrerUser(ActionEvent event) {
    		//rien mis 
     
    	}
     
    	@FXML public void annulerUser(ActionEvent event) {
    		nomTfd.setText("");
    		metierCb.setValue("");
    		List<User> userls = new java.util.ArrayList<User>();
    		userls.addAll(initialList);
    		userTbv.getItems().clear();
    		userTbv.getItems().addAll(userls);
     
     
    	}
     
    }
    Et la classe User est :
    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
     
    package com.vinou.models;
     
    import java.io.Serializable;
     
     
    public class User implements Serializable {
        private static final long serialVersionUID = -6503923891759178328L;
     
        private Long id;
        private String nom;
        private String metier;
     
    	public Long getId() {
    		return id;
    	}
     
    	public void setId(Long id) {
    		this.id = id;
    	}
     
    	public String getNom() {
    		return nom;
    	}
     
    	public void setNom(String nom) {
    		this.nom = nom;
    	}
     
     
     
    	public String getMetier() {
    		return metier;
    	}
     
    	public void setMetier(String metier) {
    		this.metier = metier;
    	}
     
    	public String toString() {
            return nom;
        }
     
     
     
    }
    Le problème semble venir du fait que lorsque l'utilisateur clique sur le bouton annuler après avoir fait une modification dans une colonne de la tableview, les valeurs ont déjà été mises à jour dans la liste initialList (il y a une liaison entre la tableview et cette liste). Aussi, les données de la tableview ne reviennent pas à celles de départ. Ce problème apparait avec l'utilisation de onEditCommit, que je suis obligé d'utiliser car sinon les valeurs ne sont pas prises en compte lorsque j'enregistre dans la base de données (la partie enregistrement consiste en fait à récupérer les valeurs dans la tableview et les envoyer vers un module chargé de faire les opération d'envoi vers la base de données ). Au niveau de la classe User et du type de ses variables, je ne peux pas utiliser de propriétés javafx (SimpleStringProperty,... ). Cette obligation est liée à l'utilisation de la classe User à d'autres endroits dans le projet (c'est un projet assez important et là j'ai reproduit la partie qui me pose problème sur un exemple perso).

    Je ne sais pas si j'ai été très claire, je vous présente mes excuses si ce n'est pas le cas mais je vous remercie d'avance pour la prise en considération de ce message.

    Cordialement,

    Vinou.

    Ajout: je ne peux pas définir la liste initiale en final vu qu'elle vient dans le vrai projet d'un autre controller qui la récupère dans la base de données. C'est ce controller qui va ouvrir sous forme de dialogbox (Stage) le controller que je vous ai montré ci-dessus. La liste est passée en paramètre lors de l'initialisation.

  5. #5
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut
    La solution de ton problème se trouve ici: http://javarevisited.blogspot.com/20...s-shallow.html
    en résumé :
    Premièrement: :
    Tu dois ajouter ce qui suit à ta classe User (qui doit en plus implémenter: l'interface Cloneable):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Override
        protected User clone() {
     
            User clone = null;
            try {
                clone = (User) super.clone();
            } catch (CloneNotSupportedException ex) {
                System.out.println(ex.getMessage());
            }
            return clone;
        }
    deuxièmement:
    pour copier une liste dans une autre, utiliser ceci:

    // dans la méthode initialize:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      userls = new java.util.ArrayList<User>(initialList.size());
            initialList.forEach(user -> userls.add(user.clone()));
            }
    // dans la méthode annulerUser():
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     userls.forEach(user -> initialList.add(user.clone()));

  6. #6
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut
    Salut.
    pour éviter d’implémenter l'interface Cloneable (bad practice!!?), je te propose de faire les choses suivantes:
    • Ajouter un constructeur qui prend en paramètre un user à la classe User (N'oublier pas d'ajouter aussi un constructeur par défaut):


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public User(User user) {
            this.id= user.id;
            this.nom = user.nom;
            this.metier = user.metier;
     
        }
    .
    • Au niveau du controller, ajouter la méthode suivante (deep copy):


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public static List<User> cloneList(List<User> userList) {
            List<User> clonedList = new ArrayList<>(userList.size());
            userList.forEach(user -> clonedList.add(new User(user)));
            return clonedList;
        }
    code complet du controller:
    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
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.ResourceBundle;
    import java.util.function.UnaryOperator;
    import javafx.beans.property.SimpleStringProperty;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Button;
    import javafx.scene.control.ComboBox;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableView;
    import javafx.scene.control.TextField;
    import javafx.scene.control.cell.ComboBoxTableCell;
    import javafx.scene.control.cell.TextFieldTableCell;
    import javafx.util.converter.DefaultStringConverter;
     
    /**
     * FXML Controller class
     *
     * @author 
     */
    public class RootController implements Initializable {
     
        @FXML
        private TextField userTfd;
        @FXML
        private TableView<User> userTbv;
        @FXML
        private TableColumn<User, String> userNomCol;
        @FXML
        private TableColumn<User, String> metierCol;
     
        @FXML
        private Button ajoutBtn;
        @FXML
        private Button modifBtn;
        @FXML
        private Button enregistrerBtn;
     
        private ObservableList<String> metiers;
        @FXML
        private TextField nomTfd;
        @FXML
        private ComboBox<String> metierCb;
        private List<User> userls;
        private List<User> initialList;
        @FXML
        Button annulerBtn;
        private final UnaryOperator<List<User>> unaryOP = RootController::cloneList;
     
        @Override
        public void initialize(URL arg0, ResourceBundle arg1) {
            initMetiers();
            initTabView();
            initMetierCb();
            initUsers();
            userls = new java.util.ArrayList<User>(initialList.size());
            userls = unaryOP.apply(initialList);
           // userls.forEach(e -> System.out.println(e + " "));
            userTbv.getItems().addAll(initialList);
        }
     
        public void initMetierCb() {
            metierCb.setItems(metiers);
        }
     
        public void initTabView() {
            userNomCol.setCellValueFactory(e -> new SimpleStringProperty(e.getValue().getNom()));
            metierCol.setCellValueFactory(e -> new SimpleStringProperty(e.getValue().getMetier()));
            userNomCol.setCellFactory(TextFieldTableCell.forTableColumn(new DefaultStringConverter()));
            metierCol.setCellFactory(ComboBoxTableCell.forTableColumn(metiers));
            userTbv.setEditable(true);
            userNomCol.setEditable(true);
     
            userNomCol.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<User, String>>() {
                @Override
                public void handle(TableColumn.CellEditEvent<User, String> t
                ) {
                    User ag = t.getTableView().getItems().get(t.getTablePosition().getRow());
                    if (t.getNewValue() != null && !((t.getNewValue()).replaceAll("\\s", "")).equals("")) {
                        ag.setNom(t.getNewValue());
                    } else {
                        ag.setNom(t.getOldValue());
                        t.getTableView().getColumns().get(0).setVisible(false);
                        t.getTableView().getColumns().get(0).setVisible(true);
                    }
                }
            });
     
            metierCol.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<User, String>>() {
                @Override
                public void handle(TableColumn.CellEditEvent<User, String> t) {
                    ((User) t.getTableView().getItems().get(t.getTablePosition().getRow())).setMetier(t.getNewValue());
                }
            });
     
        }
     
        public void initMetiers() {
            metiers = FXCollections.observableArrayList("métier 1", "métier 2", "métier 3", "métier 4", "métier 5", "métier 6");
        }
     
        public void initUsers() {
     
            User user1 = new User();
            user1.setNom("Albert");
            user1.setMetier("métier1");
            User user2 = new User();
            user2.setNom("Louis");
            user2.setMetier("métier3");
            User user3 = new User();
            user3.setNom("Marion");
            user3.setMetier("métier5");
            initialList = FXCollections.observableArrayList(user1, user2, user3);
     
        }
     
        @FXML
        public void ajouterUser(ActionEvent event) {
            User user = new User();
            user.setNom(nomTfd.getText());
            user.setMetier(metierCb.getValue());
            userTbv.getItems().add(user);
            nomTfd.setText("");
            metierCb.setValue("");
     
        }
     
        @FXML
        public void enregistrerUser(ActionEvent event) {
            //rien mis 
     
        }
     
        @FXML
        public void annulerUser(ActionEvent event) {
            nomTfd.setText("");
            metierCb.setValue("");
            initialList.clear();
            userTbv.getItems().clear();
            initialList = unaryOP.apply(userls);
            userTbv.getItems().addAll(initialList);
          //  userls.forEach(e -> System.out.println(e + " "));
     
        }
     
        public static List<User> cloneList(List<User> userList) {
            List<User> clonedList = new ArrayList<>(userList.size());
            userList.forEach(user -> clonedList.add(new User(user)));
            return clonedList;
        }
     
    }

  7. #7
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2014
    Messages
    101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2014
    Messages : 101
    Points : 71
    Points
    71
    Par défaut
    Désolé pour la réponse tardive. Je te remercie pour ta réponse. Finalement, je suis passé par une autre solution, l'utilisation de la méthode statique copyProperties de la classe BeanUtils. J'ai récupéré la librairie qui la contient via Maven (commons-beanutils). Merci pour ton aide et bon weekend.

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

Discussions similaires

  1. Binding d'une TableView éditable avec mon modèle
    Par Freddo75 dans le forum JavaFX
    Réponses: 1
    Dernier message: 26/06/2012, 05h02
  2. Réponses: 1
    Dernier message: 22/12/2009, 20h05
  3. [AJAX] Garder sélection liste déroulante
    Par arthuro45 dans le forum AJAX
    Réponses: 8
    Dernier message: 03/11/2009, 16h49
  4. Impossible de modifier menu.list
    Par fallais dans le forum Administration système
    Réponses: 1
    Dernier message: 24/06/2007, 02h54
  5. garder une liste déroulante ouverte
    Par zola dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 08/05/2006, 21h57

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