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 :

Variable cellule modifiée introuvable JTable


Sujet :

Composants Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 56
    Par défaut Variable cellule modifiée introuvable JTable
    Bonsoir,
    j'ai une Jtable qui affiche notamment des JTextArea. Mon soucis est à l'édition, dans la méthode getCellEditorValue() du TableCellEditor, qui est sensé retourner la valeur de la cellule modifiée afin qu'elle y soit affichée (si j'ai bien compris).... et bien je n'arrive pas à savoir comment trouver cette valeur. Qu'est ce que je suis sensé retourner?

    Voici l'Editor :
    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
     
    public class DescAreaCellEditor extends AbstractCellEditor implements TableCellEditor{
     
    	private String editingValue;
     
    	private static final long serialVersionUID = -9030406143699523582L;
     
        @Override  
        public Object getCellEditorValue() {
     
        	System.out.println("getCellEditorValue : " + Ppal.TableR.getValueAt(Ppal.TableR.getSelectedRow(), 8));
            System.out.println("getCellEditorValue : " + Ppal.philaTM.getValueAt(Ppal.TableR.getSelectedRow(), 8));
            return editingValue;  
        }  
     
        @Override  
        public void cancelCellEditing() {  
            super.cancelCellEditing();  
        }  
     
    	public Component getTableCellEditorComponent (	JTable table,
    													Object value,
    													boolean isSelected,
    													int row,
    													int column){
    		editingValue = value.toString();  
     
    		System.out.println("Editor : " + value.getClass());
     
    		JTextArea textArea = new JTextArea(editingValue);
            textArea.setWrapStyleWord(true);  
            textArea.setLineWrap(true);  
     
            JScrollPane pane = new JScrollPane(textArea);  
            pane.setBorder(BorderFactory.createLineBorder(Color.BLACK, 0));
            pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);  
            pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);  
            return pane;
    	}
    }
    J'ai essayé d'accéder à la donnée modifiée via la JTable et mon TableModel personnalisé mais je trouve toujours l'ancienne valeur.
    Je suis sûr que c'est tout bête mais je ne vois pas comment y arriver. Merci beaucoup à ceux qui pourraient m'aiguiller vers une piste car il doit y avoir quelque chose qui m'échappe ^^

  2. #2
    Membre expérimenté Avatar de uhrand
    Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : Luxembourg

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 203
    Par défaut
    Citation Envoyé par Ayok13 Voir le message
    dans la méthode getCellEditorValue() du TableCellEditor, qui est sensé retourner la valeur de la cellule modifiée ... je n'arrive pas à savoir comment trouver cette valeur.
    En fait, c'est extrêmement simple: nous introduisons une nouvelle variable d'instance "Object value;" que nous renvoyons dans "getCellEditorValue" et que nous modifions par "this.value = value;" dans "getTableCellEditorComponent(JTable table, Object value, ...".

    Cordialement,
    André

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 56
    Par défaut
    Ah yes ok ça y est j'ai pité! Maintenant que j'ai compris le principe effectivement tout est plus simple. Quand on sait d'où proviennent les variables qu'on reçoit et ce qu'elle représente, et aussi ce qu'on doit passer et retourner en fonctions lol

    Je vais expliciter s'il y en a qui tombent sur ce sujet si ça peut aider. En tout cas comme je l'ai compris, s'il y a des erreurs faut pas hésiter à me reprendre.
    Voici déjà ce que ça donne :



    Une table possède une TableModel qui dirige la manière dont elle se comporte. Il faut notamment qu'elle affiche les cellules (classe Renderer) et qu'on puisse éventuellement les modifier/éditer (classe Editor).

    La classe Renderer fait le pont entre les données et ce que l'utilisateur en voit dans la table, grâce à la fonction getTableCellRendererComponent(). Ce qu'on retourne est donc l'objet qui s'affiche dans la cellule. La variable "value" provient de votre structure de donnée. Dans mon cas c'est juste un String, et je renvoie un JScrollPane contenant un JTextArea qui contiendra le texte.
    J'ai vu plusieurs personnes chercher comment faire un beau JScrollPane dans une JTable, ces options permettent un retour à la ligne automatique et une scroll bar verticale qui s'affiche au besoin.

    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
     
    public class DescAreaCellRenderer implements TableCellRenderer {
     
    	private static final long serialVersionUID = -3987688353662913146L;
     
    	public Component getTableCellRendererComponent(	JTable table,
    													Object value,
    													boolean isSelected,
    													boolean hasFocus,
    													int row,
    													int column) {
            JTextArea textArea = new JTextArea(value.toString());  
            textArea.setLineWrap(true);
            textArea.setWrapStyleWord(true);
     
            JScrollPane pane = new JScrollPane(textArea);  
            pane.setBorder(BorderFactory.createLineBorder(Color.BLACK, 0));
            pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
            pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);  
            return pane;
    	}
    }
    Si on en reste là la cellule s'affiche correctement mais on ne rien en faire, il faut définir un Editor.
    La fonction getTableCellEditorComponent() permet de définir comment l'utilisateur va pouvoir modifier le contenu de la cellule, pour moi c'est tout simple j'affiche le même objet que celui qu'ils voyaient, c'est à dire un JScrollPane contenant un JTextArea mais dans lequel on peut désormais écrire. Pour une cellule colorée par exemple ça serait différent, l'édition pourrait prendre la forme d'une fenêtre qui s'ouvre avec le panel des couleurs qu'on choisirait en cliquant.
    Bref, cette fois "value" vaut ce qu'il y avait avait dans la cellule quand on a cliqué dessus (à nouveau en fait ça vient de la structure de donnée, pas du tableau en lui même). On retourne l'objet et c'est comme si on le donnait à l'utilisateur, il le modifie et nous le rend dans la fonction getCellEditorValue(). Dans cette fonction il faut faire l'opération inverse de la fonction précédente, il faut "déconstruire", pour moi je vais chercher le String à l'intérieur du JScrollPane ((JViewport) compTab[i]).getView()), et à l'intérieur du JTextArea ((JTextArea) JTextArea.getText()), et je le retourne afin qu'il soit inscrit dans la structure de données.

    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
     
    public class DescAreaCellEditor extends AbstractCellEditor implements TableCellEditor{
    	private JScrollPane editingValue;
    	private String valeurModifiée;
     
    	private static final long serialVersionUID = -9030406143699523582L;
     
        @Override  
        public Object getCellEditorValue() {
        	Component [] compTab = editingValue.getComponents();
        	for (int i=0; i<compTab.length; i++) {
        		if ("JViewport".equals (compTab[i].getClass().getSimpleName())){
                	valeurModifiée = ((JTextArea) ((JViewport) compTab[i]).getView()).getText();	
        		}	
        	}
        	return valeurModifiée;  
        }  
     
        @Override  
        public void cancelCellEditing() {  
            super.cancelCellEditing();  
        }  
     
    	public Component getTableCellEditorComponent (	JTable table,
    													Object value,
    													boolean isSelected,
    													int row,
    													int column){
     
    		JTextArea textArea = new JTextArea((String) value);
            textArea.setWrapStyleWord(true);  
            textArea.setLineWrap(true);  
     
            JScrollPane pane = new JScrollPane(textArea);  
            pane.setBorder(BorderFactory.createLineBorder(Color.BLACK, 0));
            pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);  
            pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            this.editingValue = pane;
            return pane;
    	}
    }

    Ce code ne servirait pas à grand chose s'il n'y avait pas la TableModel derrière qui structure les données et permet d'y accéder et d'y écrire. Dans mon cas c'est une List d'objets de ma classe Piece :

    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
     
    public class PhilaTableModel extends AbstractTableModel implements TableModel{
    	private String [] titresColonnes;
    	private List<Piece> lignes = new ArrayList<Piece>();
     
    	public PhilaTableModel(String [] titresColonnes){
    		this.titresColonnes = titresColonnes;
    	}
     
    	public void Ajouter (Piece ligne){
    		lignes.add(ligne);
            fireTableRowsInserted(lignes.size()-1, lignes.size() -1);
    	}
     
    	public void Inserer (int rowIndex, Piece ligne) {
    		lignes.add(rowIndex, ligne);
            fireTableRowsInserted(rowIndex, rowIndex);
    	}
     
    	public void Supprimer (int rowIndex){
    		lignes.remove (rowIndex);
    		fireTableRowsDeleted(rowIndex, rowIndex);
    	}
     
    	public void ViderTable () {
    		int Nblignes = lignes.size();
    		lignes.clear();
    		fireTableRowsDeleted(0, Nblignes);
    	}
     
    	public Class<?> getColumnClass(int columnIndex) {
    		return getValueAt(0, columnIndex).getClass();
    	}
     
    	public int getColumnCount() { return titresColonnes.length; }
    	public String getColumnName(int columnIndex) { return titresColonnes[columnIndex]; }
    	public int getRowCount() { return lignes.size(); }
    	public Object getValueAt (int rowIndex, int columnIndex) {
    		//System.out.println ("row : "+ rowIndex + " - col : " + columnIndex + " - sizeLignes : " + lignes.size());
    		switch (columnIndex){
    		case 0 :
    			return lignes.get(rowIndex).getIdPiece();
    		case 1 :
    			return lignes.get(rowIndex).getDetailsBtnCell();
    		case 2 :
    			return lignes.get(rowIndex).getPhoto();
    		case 3 :
    			return lignes.get(rowIndex).getSujet();
    		case 4 :
    			return lignes.get(rowIndex).getType();
    		case 5 :
    			return lignes.get(rowIndex).getRace();
    		case 6 :
    			return lignes.get(rowIndex).getPays();
    		case 7 :
    			return lignes.get(rowIndex).getNumero();
    		case 8 :
    			return lignes.get(rowIndex).getDescription();
    		case 9 :
    			return lignes.get(rowIndex).getValiderBtnCell();
    		case 10 :
    			return lignes.get(rowIndex).getAnnulerBtnCell();
    		case 11 :
    			return lignes.get(rowIndex).getSupprimerBtnCell();
    		case 12 :
    			return lignes.get(rowIndex).getAnnee();
    		case 13 :
    			return lignes.get(rowIndex).getTome();
    		case 14 :
    			return lignes.get(rowIndex).getEtat();
    		case 15 :
    			return lignes.get(rowIndex).getTypeDoc();
    		case 16 :
    			return lignes.get(rowIndex).getAnneeAchat();
    		case 17 :
    			return lignes.get(rowIndex).getPrix();
    		case 18 :
    			return lignes.get(rowIndex).getAnneeCote();
    		case 19 :
    			return lignes.get(rowIndex).getCoteNeuf();
    		case 20 :
    			return lignes.get(rowIndex).getCoteBon();
    		case 21 :
    			return lignes.get(rowIndex).getCoteZero();
    		case 22 :
    			return lignes.get(rowIndex).getVendeur();
    		case 23 :
    			return lignes.get(rowIndex).isManco();
    		case 24 :
    			return lignes.get(rowIndex).getValeur();
    		default :
    			return 0;
    		}
    	}
     
    	public void setValueAt (Object aValue, int rowIndex, int columnIndex) {
    		if (aValue != null) {
    			Piece piece = lignes.get (rowIndex);
    			switch (columnIndex){
    			case 3 :
    				piece.setSujet((String) aValue);
    				break;
    			case 4 :
    				piece.setType((String) aValue);
    				break;
    			case 5 :
    				piece.setRace((String) aValue);
    				break;
    			case 6 :
    				piece.setPays((String) aValue);
    				break;
    			case 7 :
    				piece.setNumero((String) aValue);
    				break;
    			case 8 :
    				piece.setDescription((String) aValue);
    				break;
    			case 9 :
    				piece.setValiderBtnCell((ValiderBtnCell) aValue);
    				break;
    			case 10 :
    				piece.setAnnulerBtnCell((AnnulerBtnCell) aValue);
    				break;
    			case 11 :
    				piece.setSupprimerBtnCell((SupprimerBtnCell) aValue);
    				break;
    			case 12 :
    				piece.setDetailsBtnCell((DetailsBtnCell) aValue);
    				break;
    			}
    			fireTableCellUpdated (rowIndex, columnIndex);
    		}
    	}
     
    	public boolean isCellEditable(int row, int col) { return col==2 ? false : true;
    	}
    }
    Voila en schéma ce que ça pourrait donner dans le comportement (enfin en espérant ne pas m'être trompé ). Là où j'ai été perdu c'est qu'il y a une sorte de boîte noire entre le TableModel et ses Renderer et Editor. Mais ce qu'il faut savoir c'est que le getTableCellRendererComponent() et getTableCellEditorComponent() font appel au getValueAt() du TableModel, et que le getTableCellEditor() effectue un setValueAt() du TableModel.



    J'ai mis les nombres comme ça car ça paraissait + logique mais en fait je pense que ça se passe plutôt comme ça :
    - l'utilisateur affiche la table
    - 2 : la table appelle le renderer pour mettre des choses dans ses cellules.
    - Boîte noire :Le renderer fait appel tableModel.
    - 1 : le tableModel lit la donnée dans la structure
    - Boîte noire : et la rend au Renderer
    - qui la retourne à son tour à la Jtable.

    - l'utilisateur clique sur une cellule pour en modifier le contenu
    - 3 : l'editor lui donne l'objet à modifier au travers le jtable
    - 4 : l'utilisateur rend l'objet à la jtable qui la transmet en fait à l'editor
    - l'editor fait appel à son tour au tableModel
    - 5 : le tableModel inscrit l'objet ou la donnée dans la structure

    Moi en tout cas ça m'a fait tilt quand j'ai compris ça, peut etre que ça servira à d'autres

  4. #4
    Membre expérimenté Avatar de uhrand
    Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : Luxembourg

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 203
    Par défaut
    Bel exposé, félicitations!

    Cependant, les "renderers" et "editors" n'ont rien à voir dans "TableModel".

    "TableModel" a justement été inventé pour rendre les données indépendantes de leur représentation graphique. Il contient uniquement les données et spécifie les méthodes que "JTable" utilise pour interroger et mettre à jour ces données.

    Les "renderers" et "editors", par contre, dirigent la manière dont "JTable" se comporte à l'écran et ils sont donc attachés à "JTable" et non pas à "TableModel". C'est d'ailleur pour cette raison que les paramètres "row" et "column" qui sont passés dans les méthodes "getTableCellRendererComponent" et "getTableCellEditorComponent" représentent la ligne et la colonne de la "JTable" et non pas ceux de "TableModel" (par exemple, en cas de tri sur une colonne, la ligne de la "JTable" sera généralement différente de la ligne correspondante de "TableModel").

    Cordialement,
    André

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 56
    Par défaut
    Merci mais j'ai encore du chemin à faire (et du temps à donner) avant de faire un bon tuto lol

    Oui effectivement, c'est vrai que je me suis rendu compte que mon schéma ne pouvait pas être bon (et en plus je viens de voir que j'avais oublié le nom de 2 fonctions getTableCellRendererComponent() pour le N°2, et getTableCellEditorComponent () pour le N°3), en fait ça ressemblerait plus à un MVC :
    http://fr.wikipedia.org/wiki/Mod%C3%...ontr%C3%B4leur

    Mais sur le coup je l'avais vu comme ça, comme une sorte de boîte noire, car les fonctions getTableCellEditor/RendererComponent () on ne les appelle jamais nous même. Je pensais donc que c'était une fonction invisible à nos yeux qui faisait une sorte de

    getTableCellRendererComponent (JTable table, TableModel.getValueAt (#), ...)

    utilisant donc TableModel pour récupérer la valeur dans la structure et la donner au renderer, qui se charge lui d'afficher cette valeur comme on le souhaite. Mais au final je ne sais toujours pas où est appelée cette fonction, comment elle est utilisée et par qui ^^
    Mais c'est clair que suite à un Sort() de la table si les renderer et editor n'étaient pas rattachés quelque part à la JTable ils seraient pommés dans leurs comptes de lignes et de colonnes

    PS: et ya aussi cette saleté de fonction getCellEditorValue() que j'ai mis du temps à comprendre car elle est trompeuse, j'y aurai plutôt vu un "set" qu'un "get" mdr

  6. #6
    Membre expérimenté Avatar de uhrand
    Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : Luxembourg

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 203
    Par défaut
    Citation Envoyé par Ayok13 Voir le message
    getTableCellRendererComponent ... je ne sais toujours pas où est appelée cette fonction, comment elle est utilisée et par qui
    Elle est utilisée par "JTable" chaque fois qu'elle a besoin de dessiner une cellule. Donc ça fait partie des mécanismes internes de "JTable" qui sont assez compliqués, c'est vrai.

    Citation Envoyé par Ayok13 Voir le message
    getCellEditorValue() ... est trompeuse, j'y aurai plutôt vu un "set" qu'un "get"
    "JTable" va appeler cette méthode pour définir une nouvelle valeur pour la cellule. Si elle ne l'appelait pas, elle n'aurait aucune idée de comment l'utilisateur a changé la valeur de la cellule.

    Cordialement,
    André

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 56
    Par défaut
    Oui voila je suis tout à fait d'accord avec toi, c'est juste que quand on démarre pour essayer de comprendre ce n'est pas forcément intuitif on va dire, mais à force de persévérance on y arrive ^^
    Comme il y en a qui disent que les JTable c'est tout pourri car juste pour afficher un élément on doit créer 50 classes et écrire 200 lignes de codes. Il y a certes une part de vérité, mais je pense que c'est le prix à payer afin de pouvoir nous fournir un outil ultra puissant complètement paramètrable et personnalisable, mais comme dans tout, quand il y a trop d'options on peut s'y perdre facilement si on ne lit pas la notice d'utilisation ^^. Le langage doit faire le choix entre puissance/complexité et généricité/facilité, mais perso je trouve qu'ils ont bien fait de se diriger vers le 1e.
    En tout cas merci pour vos précisions . Maintenant je bosse sur le Sort de ma table, là aussi je vais devoir faire un effort de compréhension, mais on va y arriver

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

Discussions similaires

  1. Utiliser une variable pour modifier la taille d'une cellule <td>
    Par morora69 dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 07/06/2010, 16h52
  2. modifier une cellule d'une JTable
    Par shakoulé dans le forum Composants
    Réponses: 5
    Dernier message: 28/11/2009, 17h28
  3. Réponses: 3
    Dernier message: 30/09/2008, 11h28
  4. jtable avec cellule modifiable lors du clic souris
    Par ASSOUMA2007 dans le forum Composants
    Réponses: 1
    Dernier message: 24/03/2007, 16h46
  5. Comment modifier une cellule dans un JTable
    Par @yoyo dans le forum Composants
    Réponses: 10
    Dernier message: 22/03/2006, 16h48

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