Eclipse (Swing) - Ajouter des composants dans un JTable

Afin d’améliorer l’ergonomie de certaines interfaces, il peut être utile d’ajouter des éléments interactifs (zones de texte, boutons radio…) directement dans les cellules d’un tableau.

Pour ce faire, l’API Swing permet de mettre rapidement en place des TableCellRenderer qui définissent le contenu des cellules. De base, une cellule est en fait un JLabel : on peut donc améliorer l’affichage en le remplaçant par une zone de texte srollable. C’est à partir de ce moment que les ennuis commencent…

Regardons tout d’abord le code nécessaire à la mise en place de cette zone de texte :

Définition du renderer personnalisé dans la dernière colonne du tableau :

Table table = new JTable() {
                    private static final long serialVersionUID = 3592907806336215067L;
                    public boolean isCellEditable(int rowIndex, int vColIndex) {
                        return (vColIndex==this.getColumnCount()-1);
                    }
                };
TableColumn col = table.getColumnModel().getColumn(resultColumnIndex);
TextAreaCellRenderer renderer = new TextAreaCellRenderer();
col.setCellRenderer(renderer);

Code du renderer :

import java.awt.Color;
import java.awt.Component;
 
import javax.swing.BorderFactory;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.DefaultTableCellRenderer;
 
public class TextAreaCellRenderer extends DefaultTableCellRenderer {
 
    private static final long serialVersionUID = -3987688353662913146L;
 
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column) {
 
        // Customize it
        JTextArea textArea = new JTextArea(value.toString());
        textArea.setEditable(false);
        textArea.setWrapStyleWord(true);
        textArea.setLineWrap(true);
        JScrollPane pane = new JScrollPane(textArea);
        pane.setBorder(BorderFactory.createLineBorder(Color.BLACK, 0));
        pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        pane
            .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        return pane;
    }
}

Ces quelques lignes suffisent à faire apparaître une zone de texte dans les cellules en question. Cependant, impossible d’utiliser les barres de défilement!! En effet, comme expliqué dans ce forum, Swing n’ajoute pas réellement la zone de texte dans la cellule, mais plutôt une image de celle-ci.

Pour rendre les barres de défilement actives, voici le principe à mettre en place :

Au clic sur la cellule, il faut entrer en mode édition. Ainsi, une nouvelle zone de texte sera définie comme CellEditor et sera utilisable!

Voici donc le complément de code à mettre en place :

Définition de l’éditeur personnalisé :

Table table = new JTable() {
                    private static final long serialVersionUID = 3592907806336215067L;
                    public boolean isCellEditable(int rowIndex, int vColIndex) {
                        return (vColIndex==this.getColumnCount()-1);
                    }
                };
TableColumn col = table.getColumnModel().getColumn(resultColumnIndex);
TextAreaCellRenderer renderer = new TextAreaCellRenderer();
TextAreaCellEditor editor = new TextAreaCellEditor();
col.setCellEditor(editor);
col.setCellRenderer(renderer);

Code de l’éditor :

import java.awt.Color;
import java.awt.Component;
 
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.TableCellEditor;
 
public class TextAreaCellEditor extends AbstractCellEditor implements
    TableCellEditor {
 
    private static final long serialVersionUID = -9030406143699523582L;
 
    private String editingValue;
 
    @Override
    public Component getTableCellEditorComponent(JTable table, Object value,
        boolean isSelected, int row, int column) {
 
        editingValue = value.toString();
 
        // Customize it
        JTextArea textArea = new JTextArea(valueStr);
        textArea.setEditable(false);
        textArea.setWrapStyleWord(true);
        textArea.setLineWrap(true);
        JScrollPane pane = new JScrollPane(textArea);
        pane.setBorder(BorderFactory.createLineBorder(Color.BLACK, 0));
        pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        pane
            .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        return pane;
    }
 
    @Override
    public Object getCellEditorValue() {
        return editingValue;
    }
 
    @Override
    public void cancelCellEditing() {
        super.cancelCellEditing();
    }
}

Maintenant, le contenu de la cellule est défilant.


Fichier(s) joint(s) :

2 commentaires:

Anonyme a dit…

Oui enfin il faudrait quand même des constructeurs dans les Renderer et Editor, et la variable valueStr oon sait pas d'où elle sort lol
Mais je suis en train de l'adapter à mon code, on verra ce que ça donne...
Si ça donne ce que je pense c'est le top ta technique

Paul-Emmanuel Faidherbe a dit…

En effet, j'ai fait quelques impasses sur des détails du code :)
J'espère avoir pu t'aider, si tu arrives à tes fins, peut être pourrais-tu m'indiquer ce que tu as réalisé et comment tu as amélioré ce code?
En tout cas bon courage!