Comment pouvoir interdire des doublons dans les lignes de ma Jtable

Résolu
coolanso Messages postés 75 Date d'inscription jeudi 12 août 2010 Statut Membre Dernière intervention 5 juillet 2014 - 2 nov. 2011 à 14:16
cs_GodConan Messages postés 2113 Date d'inscription samedi 8 novembre 2003 Statut Contributeur Dernière intervention 6 octobre 2012 - 11 nov. 2011 à 14:55
Bonjour à tous, dans mon application je dispose de deux (2) JTables A et B, l'idée est de pouvoir, en cliquant sur le bouton ajouter, copier la donnée de la ligne sélectionnée de A dans B, ce que je suis parvenu à faire sans problème, mais le hic est que la donnée copiée se place sur la première ligne de B, je voudrais qu'elle se place sur la dernière ligne, je veux dire après le dernier enregistrement de la JTable B. Aussi je voudrais pouvoir interdire d'avoir des doublons dans la table B,mes tentatives se sont chaque fois soldées par des échecs, quelqu'un pourrait-il m?aider ?

codes :

private javax.swing.JTable txtJtableRegDispo; 
private javax.swing.JTable txtJtableRegCharger;
private DefaultTableModel aModel,bModel;

//Méthodes de vérification de doublon
public boolean verif(Object[] val){
    boolean result=true;
    for(int k=0;k< txtJtableRegCharger.getModel().getRowCount();k++){
          if(txtJtableRegCharger.getModel().getValueAt(k, 0) == val){
              JOptionPane.showMessageDialog(null, val+" existe déjà", "Erreur", JOptionPane.ERROR_MESSAGE);
              result=false;
          }
        }
     return result;
}

private void CmdAjouterActionPerformed(java.awt.event.ActionEvent evt) {                                           
        // TODO add your handling code here:
// txtJtableRegDispo;  Registre (A);  txtJtableRegCharger  Registre (B)
       int i=txtJtableRegDispo.getSelectedRow();      
      int j=0;/* a ce niveau j'ai beau essayer de recuperer le nbr de ligne pour incrementé sans succès */
      Object [] valeur = {txtJtableRegDispo.getValueAt(i, 0)}; 
       bModel.insertRow(j,valeur); 
if(verif(valeur)==true ) 
        bModel.insertRow(j,valeur);   
j++ ;   
    }      

24 réponses

cs_GodConan Messages postés 2113 Date d'inscription samedi 8 novembre 2003 Statut Contributeur Dernière intervention 6 octobre 2012 12
10 nov. 2011 à 09:33
tu peux faire un truc comme ca
    private void CmdAjouterActionPerformed(java.awt.event.ActionEvent evt) {


       int i=txtJtableRegDispo.getSelectedRow();
       int c;
       Object [] valeur = {txtJtableRegDispo.getValueAt(i, 0)};
       txtJtableRegDispo.clearSelection();

           if ( isValueValide( valeur ) ){
           bModel.addRow(valeur);}
           else {/*tu peux faire un un msg d erreur si tu veux*/}

    }
    
    public boolean isValueValide( Object[] value )
    {
        int size = bModel.getRowCount();
        for ( int i = 0; i < size; i++ )
        {
            if ( value[0].equals( bModel.getValueAt(i, 0) ) ) return false;
        }
        return true;
    }


ou comme ca

        bModel = new DefaultTableModel()
        {
            public boolean isCellEditable(int row, int col)
            {
                return false;
            }

            @Override
            public void addRow(Object[] rowData)
            {
               if ( isValueValide( rowData ) ){
                super.addRow(rowData);}
               else {/*tu peux faire un un msg d erreur si tu veux*/}
            }
            
        };


mais ;o) c est pas super jolie ;o)
pour plus de liberté tu devrais quand meme faire ton propre model

class MonModel implements DefaultTableModel
{
//et la tu surcharge ou ajoute ce que tu veux ;o) ...

}


bon ;o) ca va etre dur de te macher plus le boulot ;o)

ceci dit ;o) .. pour afficher une seule colonne ;o) il est preferable d utiliser une JList plutot qu une JTable ;o)



GodConan ;o)
3
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
2 nov. 2011 à 17:16
Bonjour,

Pour ajouter une ligne à une JTable, utilises cette méthode :

((DefaultTableModel)(table.getModel())).addRow(new String[]{"", "", ""});


Par contre, il faut que tu ais fait un setModel(new DefaultTableModel()) auparavant.

Pour ce qui est des doublons, ca peut être assez complexe à gérer comme tu le fais, étant donné que les doublons doivent être acceptés lors de la recopie de la ligne. Mais ca doit pouvoir se faire en utilisant les evenements focusLost.

Ce que tu peux faire est de gérer les ajouts dans ta tables en utilisant des JTextField avec un bouton ajouter plutôt que de recopier la dernière ligne. de cette manière, tu peux vérifier que ta table ne contient pas de doublons avant d'ajouter une ligne.
0
coolanso Messages postés 75 Date d'inscription jeudi 12 août 2010 Statut Membre Dernière intervention 5 juillet 2014
2 nov. 2011 à 19:07
Bonsoir Julien39,j'ai un setModel() plus haut,je n'ai poster que la portion de code qui me semblait poser problème.Je ne sais pas si vous me comprenez ? Voici l'idée que je veux implémenter;la Jtable A est déjà remplie,elle contient déjà des lignes de données,lorsque je selectionne une ligne de cette Jtable et que je click sur Ajouter sa valeur est copiée dans la JTable B.Seulement mon code tel qu'il est ne me permet pas de gerer cette restriction.peut être que ma methode ne tourne pas rond.Et pourtant elle me semble correcte.

private void CmdAjouterActionPerformed(java.awt.event.ActionEvent evt) {                                             
    int i=txtJtableRegDispo.getSelectedRow();//recupération de l'indice de la ligne
    Object [] valeur = {txtJtableRegDispo.getValueAt(i, 0)}; //recupération de sa valeur
       if(verif(valeur)==true){//verification de doublon
           bModel.addRow(valeur);
        } 
}   


je vais l'assayer avec l'évenement focusLost comme vous l'avez dit comme vous le dite.Merci
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
3 nov. 2011 à 17:52
Je ne comprend pas vraiment ce que tu souhaites faire ici :

Object [] valeur = {txtJtableRegDispo.getValueAt(i, 0)};

Tu ne récupères que la première valeur de la ligne. Et ensuite, tu l'ajoutes au modele. Cependant, il faut que tu créé un tableau contenant toutes les valeurs de la ligne. Sinon, la dimention de la ligne n'est pas bonne.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
3 nov. 2011 à 17:54
Pour recréer ta ligne, tu peux utiliser la méthode getColumnCount() du modèle pour récupérer le nombre de lignes à copier.

Et ensuite, une boucle for qui permet de récupérer toutes les valeurs.
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
3 nov. 2011 à 17:56
Et une dernière remarque :

Remplace cette ligne ;
if(verif(valeur)==true){//verification de doublon
par
if(verif(valeur)){//verification de doublon


Le ==true ne sert à rien et montre que tu n'as pas vraiment compris la gestion des booléens en java
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
7 nov. 2011 à 08:00
Alors, tu t'en sort ?
0
cs_GodConan Messages postés 2113 Date d'inscription samedi 8 novembre 2003 Statut Contributeur Dernière intervention 6 octobre 2012 12
7 nov. 2011 à 12:08
salut ;o)

le probleme ;o) c est que si ta table est éditable ;o) ton model est de toute facon modifier a chaque saisie de valeur ;o) il est donc déja trop tard pour empecher à ce niveau l incrementation du model ;o) (puisque c est deja fait)
donc soit tu passes par un formulaire de saisie et sur la validation (ton bouton) tu incrementes (modifis) le model de la table; soit tu controle les doublons sur un datalistener et efface la mauvaise ligne (avec un petit message biensur ) soit encor mieux ;o) tu empeches carrement la saisie de mauvaise valeures au niveau du cellEditor ;o) mais c est un peu plus chaud ;o)


GodConan ;o)
0
coolanso Messages postés 75 Date d'inscription jeudi 12 août 2010 Statut Membre Dernière intervention 5 juillet 2014
8 nov. 2011 à 14:53
Salut GodConan je crois que tu m'a pas tout à fait capté,non, ma table n'est pas éditable,pour précision,je dispose de 2 tables A et B.la table A est en fait déjà rempli par les données en bd.Il s'agit pour le futur utilisateur, compte tenu du fait qu'il n'aura pas besoin de tous les elements de la table A,de sélectionner dans celle-ci les données sur lesquelles il va travailler et de les copiées dans la table B.c'est là que le probmleme de doublon se pose.Je crois que ta proposition de controler les doublons sur un datalistener pourrait resoudre mon problème.
Quand tu dis
{soit encor mieux tu empeches carrement la saisie de mauvaise valeures au niveau du cellEditor ;o)}
je ne comprends pas trop,car il n'y pas de saisie a faire.c'est juste sélectionné la ligne clicquer sur ajouter pour que la ligne soit copiée dans la table B.Merci
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
8 nov. 2011 à 15:10
Je reviens sur une idée que j'ai déjà évoquée :

Ce que tu peux faire est de gérer les ajouts dans ta tables en utilisant des JTextField avec un bouton ajouter plutôt que de recopier la dernière ligne. de cette manière, tu peux vérifier que ta table ne contient pas de doublons avant d'ajouter une ligne.


Sinon, tu vas devoir faire un renderer particulier avec la dernière ligne de ta table éditable et les autres non. Ce qui est possible mais les doublons seront plus difficiles à gérer.
0
cs_GodConan Messages postés 2113 Date d'inscription samedi 8 novembre 2003 Statut Contributeur Dernière intervention 6 octobre 2012 12
8 nov. 2011 à 15:12
si tu as 2 table c est encore plus simple ;o) ...

tu peux tout gerer au niveau des models de données...

tout tes enreg (au niveau de A, soit de ta bdd)ont une clé primaire ;o) donc tu fais suivre cette clé dans B (tu l affiches ou non, inutil de l afficher vu que faut pas la modifier) donc qd je dis dans B c est surtout au niveau du model que cela nous interresse ;o) et donc avant de faire passer tes enreg dans B il te suffi juste de controler si il est deja ou pas dans B ;o) la clé primaire identifiant les enreg de facon unique ;o) t es sur de pas te tromper ;o) ...

je ne sais pas comment tu geres tes model ;o) mais tu peux meme gerer ta table B ton SGBDD avec un model sur une table temporaire ou meme une vue ;o) ... généralement les SGBDR ;o) offrent des fonctionnalité un peu plus performante que le java sur les gros volume de données ;o)

GodConan ;o)
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
8 nov. 2011 à 15:20
Je voyais les choses plus simplement, sans nécessairement utiliser les tables temporaires, ce n'est pas un drame si la vue est déconnectée un temps du modèle. enfin, c'est vrai que cette idée est intéressante.

Ton problème n'est toujours pas réglé depuis ?
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
8 nov. 2011 à 15:21
@GodConan : ca fait plaisir de te revoir actif sur le réseau, je commençais à me sentir un peu seul...
0
cs_GodConan Messages postés 2113 Date d'inscription samedi 8 novembre 2003 Statut Contributeur Dernière intervention 6 octobre 2012 12
8 nov. 2011 à 15:34
;o) bcp de boulot... ;o) et période sans accés web ;o) c est le plus pénible ;o)

GodConan ;o)
0
coolanso Messages postés 75 Date d'inscription jeudi 12 août 2010 Statut Membre Dernière intervention 5 juillet 2014
8 nov. 2011 à 17:35
Salut Godman,j'ai dû m'absenter un moment.je crois que de tes deux proposition,je prefere de loin la première,comme SGBD,j'ai MySQL 1.2.17,je ne sais pas si on peut écrire des procedures stockées avec cette version en particulier et avec MySQL meme en géneral.voici un peu les code de mes modele de table:

private javax.swing.JTable txtJtableRegDispo;
private javax.swing.JTable txtJtableRegCharger;
// code de la table contenant les données en BD
txtJtableRegDispo = new javax.swing.JTable();
String[] tableColumnsName = {"Liste des registres disponibles"};
aModel = new DefaultTableModel() 
{ 
public boolean isCellEditable(int row, int col)
{
 return false;   
}
}; 
txtJtableRegDispo.getSelectionModel().addListSelectionListener(new RowListener());
aModel.setColumnIdentifiers(tableColumnsName);
txtJtableRegDispo.setModel(aModel);

// code de la table contenant les données copiées depuis la 1ere table

txtJtableRegCharger = new javax.swing.JTable();
String[] tableColumnsName1 = {"Liste des registres àcharger"};
bModel = new DefaultTableModel() 
{ 
public boolean isCellEditable(int row, int col)
{
 return false;   
}
}; 
bModel.setColumnIdentifiers(tableColumnsName1);
txtJtableRegCharger.setModel(bModel);

//Methodes me permettant de remplir mon tableau avec les donnée en bd
public void ListeRegistre() {
        try {
            String Query = "SELECT * FROM registres ";//ici j'ajoutes le code du registre
            Connection connection = (Connection) DataBaseConnector.getConnection();
            PreparedStatement ps = (PreparedStatement) connection.prepareStatement(Query);
            ResultSet rs = ps.executeQuery();
            ResultSetMetaData md = (ResultSetMetaData) rs.getMetaData();
            colNo = md.getColumnCount();
            while (rs.next()) {
                objects = new Object[colNo];
                for (int i = 0; i < colNo; i++) {
                    objects[i] = rs.getObject(i + 1);     
                }
                aModel.addRow(objects);
            }
            txtJtableRegDispo.repaint();

        } catch (SQLException ex) {
            Logger.getLogger(FormChoixRegistre1.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
si je te comprends tuvoudrais que j'associe chaque regitre à sa clé? mais mon problème va se situer au niveau de la copie,comment pouvoir utilier cette clé cachée afin d'effectuer les tests.Merci.je crois tu devrais plus t'ennuyer.merci pour ton aide.
0
cs_GodConan Messages postés 2113 Date d'inscription samedi 8 novembre 2003 Statut Contributeur Dernière intervention 6 octobre 2012 12
8 nov. 2011 à 19:00
;o) moi aussi ;o) je ne suis pas en permanence ;o) devant le PC ;o) ...

donc si je résume : tu 2 JTables d une seule colonne chacune ?!! (pourquoi une boucle 'for ' pour remplir ta row?)

aucun prob avec la JTable A qui est rempli à partir de ta requete (sur la table registre)

par une methode Ajouter tu fais passer des selections de A vers B... et donc ton soucis : es ce bien que sur un 2nd ajout tu risques d avoir des doublons dans B??



GodConan ;o)
0
coolanso Messages postés 75 Date d'inscription jeudi 12 août 2010 Statut Membre Dernière intervention 5 juillet 2014
9 nov. 2011 à 16:43
par une methode Ajouter tu fais passer des selections de A vers B... et donc ton soucis : es ce bien que sur un 2nd ajout tu risques d avoir des doublons dans B??

Mon souci est que je ne veux pas de doublon dans B.et je me demandais s'il n'y'avait pas dans les methodes de JTable,un evenment ou une methode dont l'implémentation me permettrai de gerer ceci.Sinon actuellement je penses à remplir un Arraylist des données de la table B et faire un control à chaque fois qu'il y'a mouvement de A vers B,mais je trouve que pour chaque click parcourir un à un mon arraylist à la recherche d'un doublon me prendrait assez de temps et rendrait mon application.Dis moi pourquoi cette méthode ne marche t-elle pas?

public boolean verif(Object[] val){
    boolean result=true;
    for(int k=0;k< txtJtableRegCharger.getModel().getRowCount();k++){
          if(txtJtableRegCharger.getModel().getValueAt(k, 0) == val){
              JOptionPane.showMessageDialog(null, val+" existe déjà", "Erreur", JOptionPane.ERROR_MESSAGE);
              result=false;
          }
        }
    
     return result;
}

 private void CmdAjouterActionPerformed(java.awt.event.ActionEvent evt) {                                           

        
       int i=txtJtableRegDispo.getSelectedRow();
       Object [] valeur = {txtJtableRegDispo.getValueAt(i, 0)}; 
       txtJtableRegDispo.clearSelection();
       if(verif(valeur)==true){
           bModel.addRow(valeur);
       }
              
    }          
0
cs_GodConan Messages postés 2113 Date d'inscription samedi 8 novembre 2003 Statut Contributeur Dernière intervention 6 octobre 2012 12
9 nov. 2011 à 17:06
C est tous simple :
sur ta table B tu mets ton propre TableModel herité de DefaultTableModel ou tu surcharges 'addRow' pour y faire ton control de doublon avant d apeller la methode super avec ou sans les donnees ;o) voulu ... ;o)

Ainsi dansl action perform tu ne fait que le addRow ... le control se fait directement au niveau de la table, c est nettement plus logique ainsi ;o) (POO)

pour le control des doublon
tu peux scanner ton model (tu verras pour quelques milliers de lignes c est encore asser reactif) ;o) ou tu peux aussi utliser ;o) quelques astuces ;o) comme la hashmap ;o) ...


GodConan ;o)
0
coolanso Messages postés 75 Date d'inscription jeudi 12 août 2010 Statut Membre Dernière intervention 5 juillet 2014
9 nov. 2011 à 18:46
salut GodConan,ma table B utilise dejà un DefaultTableModel()

private DefaultTableModel aModel,bModel;
bModel = new DefaultTableModel();

dois-je encore créer une classe une classe héritant de DefaultTableModel() du genre :

private class VerifDoublon extends DefaultTableModel{
     public void addRegistre(Object[] val) {
     }  
 }
et puis le definir dans le constructeur de DefaultTableModel comme ceci?
bModel = new DefaultTableModel(new VerifDoublon()) 
{ 
public boolean isCellEditable(int row, int col)
{
 return false;   
}
}; 
je l'ai fait ainsi,mais y'a erreur.Pour tout dire je ne vois vraiment pas comment y arriver.je suis a bout de refflection.
0
coolanso Messages postés 75 Date d'inscription jeudi 12 août 2010 Statut Membre Dernière intervention 5 juillet 2014
9 nov. 2011 à 18:51
Aussi, pourquoi j'ai pas eu de problème pour le bouton retirer qui au click retire de B les lignes selectionnées,qui pourtant utilise aussi un DefaultTableModel.j'ai jamais galerer autant,satanée JTable.je me suis promis egalement d'y arriver.
0
Rejoignez-nous