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

Composants Java Discussion :

problème Clone() sur un Model d'une Jtable


Sujet :

Composants Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juin 2010
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2010
    Messages : 26
    Par défaut problème Clone() sur un Model d'une Jtable
    Bonjour,

    j'ai poster hier : http://www.developpez.net/forums/d10...uler-retablir/
    et j'ai aussi lu ce sujet la : http://www.developpez.net/forums/d77...cloner-jtable/

    Mais j'ai un problème pour cloner le model de ma Jtable :
    Après test en mode débug, le clonage ne réussi et les 2 variables pointent sur le même objet et ne sont pas distinctes.

    JE ne voit pas ou est mon erreur.

    Je vous remercie d'avance pour votre aide.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public class TableModel extends AbstractTableModel implements Cloneable
    {
            .........
    	@Override protected Object clone() throws CloneNotSupportedException {
    		return super.clone();
    	}
            ......
    }

    Ici la partie ou je copie ma Table :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    TableModel modelSrc = (TableModel)table.getModel();
    try {
    	TableModel modelCopy = (TableModel)modelSrc.clone();
    	this.table = new JTable( modelCopy );
     
    } 
    catch( CloneNotSupportedException e ) {
    	e.printStackTrace();
    }

  2. #2
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Le problème vient tout simplement de la méthode clone que tu as implémenté. En utilisant tu ne fais qu'appeler la méthode clone de la classe Object

    Or la javadoc de la méthode clone de la classe Object indique ceci:
    The method clone for class Object performs a specific cloning operation. First, if the class of this object does not implement the interface Cloneable, then a CloneNotSupportedException is thrown. Note that all arrays are considered to implement the interface Cloneable. Otherwise, this method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned. Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.
    Il faut que savoir que l'opération de shallow copy ne fait que transmettre les références, donc chaque clone de ton modèle pointera sur le même jeu de données.

    Il va donc dans ta méthode clone implémenter ta propre manière de réaliser cette copie, vu que ce que tu cherches à faire est une deep copy. Pour celà il faut que tu commence par créer une nouvelle structure de données à partir des données existantes (et surtout ne pas utiliser directement les références).

    Par exemple si tu utilises une List appelée data pour contenir les données dans ton modèle:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    List dataCopy= new ArrayList(data.size());
    dataCopy.addAll(data);
    De cette façon ta liste dataCopy ne pointera pas sur data, donc son contenu sera différent (toutefois les références contenues dans la liste restent les mêmes vu que l'on ne les a pas clonées, donc idéalement il faut cloner tous les éléments contenus dans data et les ajouter dans dataCopy).

    De toute façon la lecture du tuto suivant te sera essentielle pour comprendre les tenants et aboutissants du clonage: http://ydisanto.developpez.com/tutor...2se/cloneable/

  3. #3
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juin 2010
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2010
    Messages : 26
    Par défaut
    @sinok

    Merci d'avoir répondu si rapidement et du temps que cela t'a pris; ça commence à être beaucoup plus clair dans ma tête.
    je vais prendre le temps de lire ce tuto à fond.
    Bonne fin de journée.

    Edit : Après lecture du tutorial dont sinok a donné le lien, j'ai modifié ma classe TableModel comme suit :

    rajout d'un constructeur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        public TableModel( List<Object[]> data )
        {
        	this._data2 = data;
        }

    La méthode clone
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    	@Override protected Object clone() throws CloneNotSupportedException 
    	{		
    		List<Object[]> dataCopy = new ArrayList<Object[]>();
    		dataCopy.addAll( _data2 );
    		TableModel model = new TableModel( dataCopy );		
    		return model;
    	}
    Pour ceux que ça intéresserai.

    Merci encore.

  4. #4
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juin 2010
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2010
    Messages : 26
    Par défaut
    Petit ajout j'ai mis 2 jours à trouver mon erreur !
    mon Undo-Redo fonctionné quand je supprimer une ligne de ma table, ou en ajouter une, mais pas quand je modifier le contenu d'une ligne, c'est seulement en relisant le tutorial http://ydisanto.developpez.com/tutor...2se/cloneable/

    On voit bien que les deux tableaux sont deux instances différentes, mais on remarque aussi que les objets contenus pointent vers la même instance, ils n'ont donc pas été clonés.
    Or le List<Object[]> contenu dans le model de la table n'y fait pas exception !

    si on veut vraiment une copie parfaite, il vaut mieux faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    		List<Object[]> dataCopy = new ArrayList<Object[]>();
    		for( int i=0; i<_data2.size(); i++ )
    		{
    			Object[] currentRow = _data2.get(i).clone();
    			dataCopy.add( currentRow );
    		}
    A la place de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    List<Object[]> dataCopy = new ArrayList<Object[]>();
    		dataCopy.addAll( _data2 );

  5. #5
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    C'est ce que j'indiquait à la fin de mon dernier message...

  6. #6
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juin 2010
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2010
    Messages : 26
    Par défaut
    @sinok
    Ouais je sais, on va toujours trop vite à lire et on croit avoir compris...

    Merci encore sinok

  7. #7
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par teroux Voir le message
    La méthode clone
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    	@Override protected Object clone() throws CloneNotSupportedException 
    	{		
    		List<Object[]> dataCopy = new ArrayList<Object[]>();
    		dataCopy.addAll( _data2 );
    		TableModel model = new TableModel( dataCopy );		
    		return model;
    	}
    Pour ceux que ça intéresserai.
    Attention ceci n'est pas correct ! Il faut impérativement appeler la méthode super.clone() sinon tu casses le principe du clone pour les classes filles.


    • Soit tu utilises un constructeur de copie sans la méthode clone().
    • Soit tu utilises la méthode clone() en revoyant l'objet créé par super.clone()


    La méthode clone() doit renvoyer le même type que l'instance et non pas un type fixe.


    Dans ton cas la méthode clone() devrait plutôt ressembler à ceci :
    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
    	@Override
    	protected Object clone() throws CloneNotSupportedException {
    		// 1. Clone de l'objet lui-même
    		TableModel clone = (TableModel) super.clone();
     
    		// 2. Clone ou création de chaque attribut de la classe courante :
    		clone.dataCopy = new ArrayList<Object[]>();
     
    		// 3. Clone ou création récursive selon le cas
    		for (Object[] array : this.dataCopy) {
    			clone.dataCopy.add( array.clone() );
    		}
     
    		// 4 Retour de l'élément cloné
    		return clone;
    	}
    A noter que selon leurs types, les éléments des tableaux Object[] pourrait avoir besoin d'être également clonée.


    A noter que selon le besoin on peut passer la méthode en public, mais surtout que l'on peut se débarrasser de l'exception qui ne devrait jamais arriver du moment qu'on implémente bien Cloneable :
    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
    	@Override
    	public Object clone() {
    		try {
    			// 1. Clone de l'objet lui-même
    			TableModel clone = (TableModel) super.clone();
     
    			// 2. Clone ou création de chaque attribut de la classe courante :
    			clone.dataCopy = new ArrayList<Object[]>();
     
    			// 3. Clone ou création récursive selon le cas
    			for (Object[] array : this.dataCopy) {
    				clone.dataCopy.add( array.clone() );
    			}
     
    			// 4 Retour de l'élément cloné
    			return clone;
    		} catch (CloneNotSupportedException e) {
    			// Ceci ne devrait jamais arrivé :
    			throw new RuntimeException(e);
    		}
    	}

    a++

  8. #8
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juin 2010
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2010
    Messages : 26
    Par défaut
    @adiGuba
    Merci pour ce complément d'informations et pour les corrections.
    J'ai mis à jour mon code.

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

Discussions similaires

  1. Listener sur les titres d'une JTable
    Par AnjouWeb dans le forum Composants
    Réponses: 7
    Dernier message: 13/07/2007, 17h31
  2. ActionListener sur un bouton d'une Jtable
    Par tchoukapi dans le forum Composants
    Réponses: 2
    Dernier message: 10/07/2007, 17h25
  3. problème de couleur de cellule dans une JTable
    Par rprom1 dans le forum Composants
    Réponses: 3
    Dernier message: 04/04/2007, 00h01
  4. Focus sur la selection d'une jTable
    Par delma dans le forum Composants
    Réponses: 2
    Dernier message: 25/11/2006, 12h47
  5. PB du caret sur un JTextField dans une Jtable
    Par jeffciara dans le forum Composants
    Réponses: 4
    Dernier message: 14/11/2006, 18h48

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