In Java, ogni tabella utilizza un modello per gestire i dati rappresentati.
Il modello in questione deve implementare i metodi definiti nell’interfaccia javax.swing.table.TableModel. Qualora non venisse specificato un modello, la classe JTable crea un’istanza di javax.swing.table.DefaultTableModel


Table model

Nell’esempio che segue, creeremo una classe Person che rappresenterà il dato da mostrare in una riga della tabella.
Estenderemo la classe import javax.swing.table.AbstractTableModel, che esonera il programmatore dal dover implementare tutti i metodi dell’interfaccia TableModel, effettuando l’overriding dei soli metodi necessari e utilizzeremo tale model in una JTable.
Verrà inoltre mostrato come creare una cella contenente una combo box (per la scelta del sesso):

Person.java

package test;

public class Person
{
    private String firstName;
    private String lastName;
    private String sex;

    public Person()
    {
        this("", "", "");
    }

    public Person(String firstName, String lastName, String sex)
    {
        this.firstName = firstName;
        this.lastName = lastName;
        this.sex = sex;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

PersonTableModel.java

package test;

import javax.swing.table.AbstractTableModel;
import java.util.Vector;

public class PersonTableModel extends AbstractTableModel
{
    Vector<Person> content;
    String[] headers;

    public PersonTableModel()
    {
        content = new Vector<Person>();
        headers = new String[]{"Nome", "Cognome", "Sesso"};
    }

    // numero di righe
    public int getRowCount()
    {
        return this.content.size();
    }

    // numero di colonne
    public int getColumnCount()
    {
        return headers.length;
    }

    // nome di una determinata colonna
    @Override
    public String getColumnName(int columnIndex)
    {
        return headers[columnIndex];
    }

    // valore di una determinata cella
    public Object getValueAt(int rowIndex, int columnIndex)
    {
        Person row = content.elementAt(rowIndex);
        if(columnIndex == 0)
        {
            return row.getFirstName();
        }
        else if(columnIndex == 1)
        {
            return row.getLastName();
        }
        else if(columnIndex == 2)
        {
            return row.getSex();
        }

        return null;
    }

    // setto il valore di una cella
    // viene richiamato subito dopo l'editing fatto attraverso la GUI
    @Override
    public void setValueAt(Object value, int rowIndex, int columnIndex)
    {
        Person row = this.content.elementAt(rowIndex);
        String strValue = (String)value;
        if(columnIndex == 0)
        {
            row.setFirstName(strValue);
        }
        else if(columnIndex == 1)
        {
            row.setLastName(strValue);
        }
        else if(columnIndex == 2)
        {
            row.setSex(strValue);
        }
    }

    // Sempre true indica che qualsiasi cella è editabile
    @Override
    public boolean isCellEditable(int rowIndex, int colIndex)
    {
        return true;
    }

    // utilizzata per differenziare la classe con cui è rappresentata
    // una colonna (usata per la nostra combo box)
    @Override
    public Class getColumnClass(int colIndex)
    {
        return this.getValueAt(0, colIndex).getClass();
    }

    // aggiungo n persone
    public void addPeople(Person... persons)
    {
        for(Person person : persons)
        {
            this.content.add(person);
        }
    }

}

Main.java

package test;

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JTable;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class Main extends JFrame
{
    private JTable table;
    private PersonTableModel model;

    public Main()
    {
        super("JTable test");

        // creo il modello
        model = new PersonTableModel();
        model.addPeople(
                new Person("Antonio","Tancredi", "Uomo"),
                new Person("Maria", "Bianchi", "Donna"),
                new Person("Massimo", "Verdi", "Uomo")
             );

        // setto il modello
        this.table = new JTable(model);
        this.table.setFillsViewportHeight(true);

        // creo la combobox
        JComboBox comboBox =
            this.createComboBox("Uomo", "Donna");
        // setto, come editor della colonna 2, la combo box
        table.getColumnModel().getColumn(2).setCellEditor(
                        new DefaultCellEditor(comboBox));

        this.getContentPane().add(new JScrollPane(this.table));
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(300, 300);
        this.setLocationRelativeTo(null);
    }

    public JComboBox createComboBox(String... items)
    {
        JComboBox retv = new JComboBox();
        for(String item : items)
        {
            retv.addItem(item);
        }

        return retv;
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    new Main().setVisible(true);
                }
            }
        );
    }

}

Il risultato è il seguente:



Table Model