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 :

Binding entre une TableView et deux TextField (JavaFX 2.0)


Sujet :

JavaFX

  1. #1
    Futur Membre du Club
    Inscrit en
    Mars 2003
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Mars 2003
    Messages : 9
    Points : 9
    Points
    9
    Par défaut Binding entre une TableView et deux TextField (JavaFX 2.0)
    Bonjour à vous

    Depuis plusieurs jours, je cherche une solution pour faire la liaison entre ma TableView et mes TextField (qui servent à éditer ma TableView)

    Le principe :
    Les données (Personne) sont lues en JPA depuis une DB (PersonneDAO). Ce sont des simples POJO. Ces données sont affichées dans une TableView.
    Je voudrais que lorsqu'on sélectionne une ligne dans la TableView, les TextField se remplissent avec les données de la TableView et lorsque l'on modifier le contenu des TextField, la ligne sélectionnée de la TableView soit modifiée directement.

    J'ai chercher des exemples via google afin de mieux comprendre le mécanisme du binding mais rien ne m'a permis de trouver une solution. J'ai tenté de me baser sur le site http://ugate.wordpress.com/2012/07/3...ings-part-iii/ mais rien à faire.

    Voici mes sources :

    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
    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.event.EventHandler;
    import javafx.geometry.Insets;
    import javafx.scene.Scene;
    import javafx.scene.control.*;
    import javafx.scene.control.cell.PropertyValueFactory;
    import javafx.scene.input.MouseButton;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.HBox;
    import javafx.stage.Stage;
    import jfxtras.labs.scene.control.BeanPathAdapter;
     
    import java.util.ArrayList;
    import java.util.List;
     
    public class TestAppl extends Application {
     
      private TableView<Personne> tv;
      private TextField tfNom;
      private TextField tfPrenom;
      private ObservableList<Personne> personnes;
     
      private Personne p = new Personne();
      private BeanPathAdapter<Personne> personPA = new BeanPathAdapter<>(p);
     
      @Override
      public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("Test de TableView");
     
        Scene scene = new Scene(new BorderPane(), 800, 500);
        primaryStage.setScene(scene);
     
        PersonneDAO personneDAO = new PersonneDAO();
     
        HBox pan = new HBox();
        pan.setPadding(new Insets(10, 10, 10, 10));
        pan.setSpacing(5);
        tfNom = new TextField();
        tfPrenom = new TextField();
     
        pan.getChildren().addAll(tfNom, tfPrenom);
        ((BorderPane) scene.getRoot()).setTop(pan);
     
        tv = new TableView<>();
     
        TableColumn<Personne, String> nomCol = new TableColumn("Nom");
        nomCol.setCellValueFactory(new PropertyValueFactory("nom"));
     
        TableColumn<Personne, String> prenomCol = new TableColumn("Prénom");
        prenomCol.setCellValueFactory(new PropertyValueFactory("prenom"));
     
        tv.getColumns().addAll(nomCol, prenomCol);
     
        personnes = FXCollections.observableArrayList(personneDAO.getPersonnes());
        tv.getItems().addAll(personnes);
     
        tv.setOnMouseClicked(new EventHandler<MouseEvent>() {
          @Override
          public void handle(MouseEvent mouseEvent) {
            if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {
              if (mouseEvent.getClickCount() == 1) {
                personPA.setBean(tv.getSelectionModel().getSelectedItem());
                personPA.bindBidirectional("nom", tfNom.textProperty());
                personPA.bindBidirectional("prenom", tfPrenom.textProperty());
              }
            }
          }
        });
     
        ((BorderPane) scene.getRoot()).setCenter(tv);
     
        primaryStage.show();
      }
     
      public static void main(String[] args) {
        Application.launch(args);
      }
    Le bean Personne :
    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
     public class Personne {
        private String nom;
        private String prenom;
     
        public Personne() {
        }
     
        public Personne(String nom, String prenom) {
          this.nom = nom;
          this.prenom = prenom;
        }
     
        public String getNom() {
          return nom;
        }
     
        public void setNom(String nom) {
          this.nom = nom;
        }
     
        public String getPrenom() {
          return prenom;
        }
     
        public void setPrenom(String prenom) {
          this.prenom = prenom;
        }
      }
    Et le futur DAO :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     public class PersonneDAO {
     
        public List<Personne> getPersonnes() {
          List<Personne> pers = new ArrayList<>();
          pers.add(new Personne("Nom1", "prenom1"));
          pers.add(new Personne("Nom2", "prenom2"));
          pers.add(new Personne("Nom3", "prenom3"));
          return pers;
        }
      }
    Je vous remercie de m'avoir lu et si quelqu'un à une idée ...
    Je vous souhaite une bonne journée.

    Neo

  2. #2
    Membre chevronné
    Avatar de la.lune
    Homme Profil pro
    Directeur Technique
    Inscrit en
    Décembre 2010
    Messages
    545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Comores

    Informations professionnelles :
    Activité : Directeur Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2010
    Messages : 545
    Points : 2 084
    Points
    2 084
    Par défaut
    Bonjour!
    Ton problème d'abord c'est qu'en JavaFX on ne définit pas les beans comme tu l'a défini, il y a une manière très précise pour définir les beans, comme j'ai fais avec la classe Personne.

    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
     
    package testappl;
     
    import javafx.beans.property.SimpleStringProperty;
    import javafx.beans.property.StringProperty;
     
     
    public class Personne {
     
        private StringProperty nom;
        private StringProperty prenom;
     
     
     public Personne(String nom, String prenom){
     this.nom=new SimpleStringProperty(nom);
     this.prenom=new SimpleStringProperty(prenom);
     }
        public final String getNom() {
          return nom.get();
        }
     
        public final void setNom(String nom) {
          this.nom.set(nom);
        }
        public StringProperty nomProperty(){
            return nom;
     
        }
     
        public final String getPrenom() {
          return prenom.get();
        }
     
        public final void setPrenom(String prenom) {
          this.prenom.set(prenom);
        }
       public StringProperty prenomProperty(){
       return prenom;}
      }
    Il ne faut pas oublier pour les méthodes nonProperty() et prenomProperty() : non et prenom doivent être en minuscule comme ils sont déclarés, et tu garde la même forme comme sur les nom des colones sur le Tableview comme tu as déjà fait.

    Après j'ai enlevé la librairie jfxtras que tu as utilisé, on a pas besoin du BeanPathAdapter, l’implémentation de l'API javafx suffit.

    Donc l'astuce c'est qu'à chaque sélection d'une ligne on bind bidirectionnellement les textFields avec les propriétés du bean Personne contenu sur la ligne sélectionné, mais il ne faut pas oublier d'unbinder avant ce qui a été précédemment bindé. D'où la nécessite d'avoir un bean Personne en cours qui va pointer sur la personne sélectionné. Et quand tu ajoutes la liste Personne au tableview, lui il binde ces cellules aux propriétés du bean, à condition que ce dernier respecte les normes des beans en Javafx. J'ai illustré dans l'image suivant les binding, les flèches à sens uniques explicitent les bindings à sens unique et le double flèche c'est pour les bindings bidirectionels.

    Voici le 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
    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
     
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package testappl;
     
     
    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.event.EventHandler;
    import javafx.geometry.Insets;
    import javafx.scene.Scene;
    import javafx.scene.control.*;
    import javafx.scene.control.cell.PropertyValueFactory;
    import javafx.scene.input.MouseButton;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.HBox;
    import javafx.stage.Stage;
     
     
     
    public class TestAppl extends Application {
     
      private TableView<Personne> tv;
      private TextField tfNom;
      private TextField tfPrenom;
      private ObservableList<Personne> personnes;
      //La personne sléctioné
      private Personne pEnCours;
     
      @Override
      public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("Test de TableView");
     
        Scene scene = new Scene(new BorderPane(), 800, 500);
        primaryStage.setScene(scene);
     
        PersonneDAO personneDAO = new PersonneDAO();
     
        HBox pan = new HBox();
        pan.setPadding(new Insets(10, 10, 10, 10));
        pan.setSpacing(5);
        tfNom = new TextField();
        tfPrenom = new TextField();
     
        pan.getChildren().addAll(tfNom, tfPrenom);
        ((BorderPane) scene.getRoot()).setTop(pan);
     
        tv = new TableView<>();
     
        TableColumn nomCol = new TableColumn("Nom");
        nomCol.setCellValueFactory(new PropertyValueFactory("nom"));
     
        TableColumn prenomCol = new TableColumn("Prénom");
        prenomCol.setCellValueFactory(new PropertyValueFactory("prenom"));
     
        tv.getColumns().addAll(nomCol, prenomCol);
     
        personnes = FXCollections.observableArrayList(personneDAO.getPersonnes());
        tv.getItems().addAll(personnes);
        tv.setOnMouseClicked(new EventHandler<MouseEvent>() {
          @Override
            public void handle(MouseEvent mouseEvent) {
              if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {
                if (mouseEvent.getClickCount() == 1) {
     
                   if(pEnCours!=null){  
                    tfNom.textProperty().unbindBidirectional(pEnCours.nomProperty());
                    tfPrenom.textProperty().unbindBidirectional(pEnCours.prenomProperty());
                    }
                    pEnCours=tv.getSelectionModel().getSelectedItem();
                    //Attribuer de nouveaux liens 
                    tfNom.textProperty().bindBidirectional(pEnCours.nomProperty());
                    tfPrenom.textProperty().bindBidirectional(pEnCours.prenomProperty());
     
              }
            }
          }
        });
     
        ((BorderPane) scene.getRoot()).setCenter(tv);
     
        primaryStage.show();
      }
     
      public static void main(String[] args) {
        Application.launch(args);
      }
    }
    Pour la classe PersonneDAO je ne l'ai pas touché, car tu aura juste a remplir ta liste avec les données de la base de données.
    Il y a une possibilité d'écouter les changement à chaque personne dont les propriétés sont modifiés ou au moins savoir que les valeurs ne sont pas les mêmes avec les ChangeListener ou les InvalidationListerner qu'on peut ajouter au prorprietés de bean personne.

    En tout cas personnellement je n'ai pas cherché à comprendre le contenu de l'article que tu as publié, il reste qu'il y a encore d'autres choses concernant les POJOs je n'ai rien touché, alors bonne continuation.

  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
    Hum, il y a une ou plusieurs classes adaptateur quelques part dans l'API qui permettent de connecter une propriété d'un java bean comme une propriété JavaFX il me semble (j'oublie a chaque fois son nom).

    Grosso-modo ce qu'elles font c'est placer les PropertyChangeListener (les event Java bean) qui vont bien sur les propriétés du bean et forwarder les ChangeListener (les events FX) au moment approprie et packager le tout sous une ObservableValue. Rien qui ne puisse être fait a mano assez rapidement.
    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
    Futur Membre du Club
    Inscrit en
    Mars 2003
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Mars 2003
    Messages : 9
    Points : 9
    Points
    9
    Par défaut
    Merci à vous pour vos réponses.

    J'ai été un peu long à répondre car j'ai du avancer sur mon projet et j'avais réussi à trouver une solution un peu 'pourrie' car j'avais des délais à respecter.

    Merci la.lune pour toute ton explication. Je vais l'étudier ce weekend afin de mieux comprendre les properties et le binding. J'ai l'impression qu'il me faudra faire pour chaque bean JPA un convertisseur vers des beans FX (avec des properties). Ce qui ne m'enchante pas vraiment car j'ai près de 500 beans JPA qui ne sont pas toujours des plus simples.

    bouye, les adaptateurs dont tu parles, ce ne serait pas justement les BeanPathAdapter ? C'est ce que j'avais tenté de mettre en place mais je n'y étais pas arrivé.

    La solution que j'avais trouvé était de me passer du binding et de placer un bouton de validation pour l'édition. Lorsque l'on valide les champs édités, je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Personne selectedPersonne = (Personne)tableView.getSelectionModel().getSelectedItem();
    int index = tableView.getItems().indexOf(selectedPersonne );
    if (index != -1) {
              tableView.getItems().remove(index);
              tableView.layout();
              tableView.getItems().add(index, selectedPersonne );
              tableView.getSelectionModel().select(index);
    }
    Cette solution ne me plaisait pas du tout mais elle m'a dépanné.

    Dès que j'aurai un peu de temps, je reviendrai sur ce bout de code afin de tenter de mettre en place une de vos propositions car, venant du Swing, j'ai des lacunes avec ces concepts.

    En tout cas, je vous remercie tous les deux.
    Neo

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. Problème de bind entre une JTable et une BD
    Par snips67 dans le forum NetBeans Platform
    Réponses: 1
    Dernier message: 13/09/2010, 14h39
  3. Réponses: 2
    Dernier message: 26/05/2010, 16h29
  4. Binding entre deux UserControl
    Par mehdi_ouni dans le forum Windows Presentation Foundation
    Réponses: 3
    Dernier message: 11/03/2008, 16h10
  5. [WPF] Problème de binding entre une SortedList et une ListBox
    Par JuTs dans le forum Général Dotnet
    Réponses: 4
    Dernier message: 10/12/2007, 13h20

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