Composant JTable

Le composant JTable permet de créer des tableaux. On l'utilise en relation avec une classe dérivée de AbstractTableModel qui permet de décrire le contenu du tableau (nombre de lignes et de colonnes, contenu des cellules).

Nous allons écrire une application qui affichera dans un tableau le contenu d'un fichier de données au format texte utilisant la virgule comme séparateur. La première ligne du fichier donnera les titres des colonnes du tableau.

La classe DataFileTableModel

Cette classe dérivée de la classe AbstractTableModel devra implémenter un certain nombre de méthodes déclarées abstraites. Elle utilisera pour ce faire les données contenues dans un fichier.

Déclaration et variables

Nous utiliserons trois variables:

On obtient le code suivant:

        import javax.swing.*;
        import javax.swing.table.*;
        import java.io.*;
        import java.util.*;

        public class DataFileTableModel extends AbstractTableModel {
         protected Vector data;            //données
         protected Vector columnNames ;    //noms de colonnes
         protected String datafile;        //nom du fichier de données

Constructeur

Le constructeur récupère le nom du fichier de données puis initialise les deux champs de type Vector en lisant le fichier dans la méthode initVectors.

         public DataFileTableModel(String f) {
          datafile=f;
          initVectors();
         }
 
         public void initVectors() {
          String ligne;
          data=new Vector();
          columnNames=new Vector();
          try {
           FileInputStream fin=new FileInputStream(datafile);
           BufferedReader br=new BufferedReader(
            new InputStreamReader(fin));
           // lecture des noms de colonnes (1ère ligne)
           ligne=br.readLine();
           StringTokenizer st1=new StringTokenizer(ligne, ",");
           while(st1.hasMoreTokens())
            columnNames.addElement(st1.nextToken());
           // lecture des données
           while ((ligne = br.readLine()) != null) {
            StringTokenizer st2=new StringTokenizer(ligne, ",");
            while(st2.hasMoreTokens())
             data.addElement(st2.nextToken());
            }
           br.close();
          } catch (Exception e) {
           e.printStackTrace();
          }
         }

La première ligne du fichier permet de déterminer le nombre et les noms des colonnes, elle sert donc à initialiser le champ columnNames. Les lignes suivantes permettent d'initialiser le champ data.

Méthodes à implémenter

Il nous reste à implémenter les méthodes qui permettront de construire et d'afficher le tableau.

Nombre de colonnes

Le nombre de colonnes est le nombre d'éléments du champ columnNmes.

         public int getColumnCount() {
          return columnNames.size();
         }

Nombre de lignes

Le nombre de lignes est obtenu en divisant le nombre d'éléments du champ data par le nombre de colonnes.

         public int getRowCount() {
          return data.size()/getColumnCount();
         }

Noms des colonnes

Les noms des colonnes sont contenus dans le champ columnNames.

         public String getColumnName(int columnIndex) {
          String colName="";
          if (columnIndex<=getColumnCount())
           colName=(String)columnNames.elementAt(columnIndex);
          return colName;
         }

Type de contenu d'une colonne

Dans notre exemple, toutes les données sont des chaînes de caractères, donc de classe String.

         public Class getColumnClass(int columnIndex){
          return String.class;
         }

Possibilité d'édition des données

On indique ici quelles cellules sont modifiables. Dans notre exemple, aucune cellule ne le sera.

         public boolean isCellEditable(int rowIndex, int columnIndex) {
          return false;
         }

Contenu d'une cellule

On donne ici le contenu de chaque cellule sous forme d'objet. Dans notre exemple, ce contenu est une chaîne de caractères contenue dans le champ data. Il faut tenir compte du fait que les données sont placées les unes derrière les autres et donc recalculer leur position en fonction de la ligne et de la colonne de la cellule.

         public Object getValueAt(int rowIndex, int columnIndex) {
          return (String)data.elementAt(
                   (rowIndex*getColumnCount())+columnIndex);
         }

Changement du contenu d'une cellule

On indique ici comment prendre en compte les modifications du contenu des cellules effectuées par l'utilisateur. Dans notre exemple, aucune cellule n'est éditable, il n'y a donc rien à faire.

         public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
         }

L'application

Nous allons construire un JPanel qui contiendra un élément JTable associé au DataFileTableModel créé précédemment.

Il nous suffira ensuite d'écrire une méthode main qui créera une fenêtre contenant le JPanel créé.

Déclarations

On importe les packages nécessaires et on fait dériver la classe DataFileTable de la classe JPanel.

        import javax.swing.*;
        import java.awt.event.*;
        import java.awt.*;
        import java.io.*;
        import java.util.*;

        public class DataFileTable extends JPanel {
        }

Constructeur

On récupère le nom du fichier de données (qui sera déterminé dans la méthode main), puis on crée le modèle de table et la table. La table est placée dans un JScrollPane pour obtenir des ascenceurs lorsque c'est nécessaire.

         public DataFileTable(String dataFilePath) {
          JTable table;                // le tableau
          DataFileTableModel model;    // le modèle
          //fonte
          Font f=new Font("SanSerif",Font.PLAIN,24);
          setFont(f);
          //gestionnaire de positionnement
          setLayout(new BorderLayout());
          //construction du modèle de remplissage à partir du fichier
          model = new DataFileTableModel(dataFilePath);
          //création du tableau
          table=new JTable();
          table.setModel(model);
          table.createDefaultColumnsFromModel();
          //scroller
          JScrollPane scrollpane=new JScrollPane(table);
          add(scrollpane);
         }

Dimensions préférées

La méthode getPreferredSize() permet de fixer les dimensions préférées du tableau.

         public Dimension getPreferredSize() {
          return new Dimension(400, 300);
         }

Méthode main

La méthode principale permet de récupérer un nom de fichier en paramètre, puis de créer un tableau de type DataFileTable et de l'insérer dans une fenêtre.

         public static void main(String args[]) {
          //la fenêtre du programme
          JFrame fen=new JFrame("Table");
          //le tableau
          DataFileTable tablo;
          String nomFichier="datas.txt";
          if (args.length>0) nomFichier=args[0];
          tablo=new DataFileTable(nomFichier);
          //configuration de la fenêtre
          fen.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
          fen.setForeground(Color.black);
          fen.setBackground(Color.lightGray);
          fen.getContentPane().add(tablo,"Center");
          fen.setSize(tablo.getPreferredSize());
          //affichage
          fen.setVisible(true);
          //écouteur pour fermeture
          fen.addWindowListener(new WindowCloser());
         }

La classe WindowCloser

Il reste à créer la classe WindowCloser chargée de la gestion des évènements liés à la fenêtre.

        class WindowCloser extends WindowAdapter {
         public void windowClosing(WindowEvent e) {
          Window win=e.getWindow();
          //effacer la fenêtre
          win.setVisible(false);
          //terminer le programme
          System.exit(0);
         }
        }



Retour au menu