Bom dia Jfalca.
Como o próprio nome já diz, [color=red]Default[/color]TableModel é um tipo de model padrão para tabelas, que eu costumo chamar de model engessado, que não permite voce dinamizá-lo.
Já o AbstractTableModel, permite voce definir o nome das colunas, bem como de popular o seu JTable, passando-lhe os dados via construtor da classe ou via métodos, com isto, voce pode construir varios models com AbstractTableModel e exibí-los em apenas um JTabel, através do método “setModel(…)”.
Vamos ao seu exemplo de cadastro de clientes. Primeiramente vamos criar uma entidade de dados a qual costumamos chamar de Bean, com o nome de ClienteBean, esta classe é que vai navegar com os seus dados populados, e depois a classe AbstractTableModel.
// Classe ClienteBean
public class ClienteBean {
private Integer cod, idade;
private String nome;
public Integer getCod() {
return cod;
}
public void setCod(Integer cod) {
this.cod = cod;
}
public Integer getIdade() {
return idade;
}
public void setIdade(Integer idade) {
this.idade = idade;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
// Classe AbstractTableModel
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
public class ClienteModel extends AbstractTableModel {
// Lista que vai conter todos os dados do JTable
private List<ClienteBean> dataset;
// Constante que defini o nome das colunas
private static final String[] col = {"Código","Nome","Idade"};
// Construtor da classe recebe os dados a ser populado
public ClienteModel(List<ClienteBean> bean) {
dataset = new ArrayList<UsuarioBean>(bean);
fireTableStructureChanged();
}
// Método sobrescrito que retorna o número de linhas do JTable, após populado
@Override
public int getRowCount() {
return dataset.size();
}
// Método sobrescrito que retorna o número de colunas do JTable após populado
@Override
public int getColumnCount() {
return col.length;
}
// Método sobrescrito que vai popular e retornar cada célula do JTable
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
ClienteBean cbean = dataset.get(rowIndex);
Object row = null;
switch (columnIndex){
case 0: row = cbean.getCod(); break;
case 1: row = cbean.getNome(); break;
case 2: row = cbean.getIdade(); break;
}
return row;
}
/* Este método sobrescrito, defini se o JTable será editável ou não.
Voce pode definir qual coluna de qual linha será editável. Caso voce
defina que o seu JTable seja editável, então é necessário definir também
o método "setValueAt" que vem logo a seguir, caso contrário, é só retornar
false para todas as linhas e colunas, como definido abaixo. */
@Override
public boolean isCellEditable(int rowIndex, int columnIndex){
return false;
}
/* Este método sobrescrito, permite voce editar o JTable, caso o método anterior
tenha algumas colunas de algumas ou todas linhas editáveis setadas para true,
ou que tenha como retorno o valor true para todas as linhas e colunas. */
@Override
public void setValueAt(Object value, int row, int col) {
ClienteBean dado = dataset.get(row);
switch (col){
case 0: dado.setCod((Integer)value); break;
case 1: dado.setNome((String)value); break;
case 2: dado.setIdade((Integer)value); break;
}
fireTableCellUpdated(row, col);
}
// Este método sobrescrito defini que tipo de dado será retornado para cada coluna
@Override
public Class getColumnClass(int column){
if (column == 0 || column == 2) {
return Integer.class;
} else {
return String.class;
}
}
/* Este método criado por nós, vai retornar o conjunto
de dados inteiro do JTable, através de um List contendo
Objetos ClienteBean populados. */
public List<UsuarioBean> getDataSet(){
return dataset;
}
/* Este método sobrescrito vai definir o nome das colunas
que foi atribuído na constante "col" logo no início da classe */
@Override
public String getColumnName(int column){
return col[column];
}
/* Este método foi criado por nós para retornar um objeto ClienteBean
populado, de acordo com o número de linha do JTable fornecido pelo
parâmetro "int row" */
public ClienteBean getRow(int row) {
return dataset.get(row);
}
/* Este método criado por nós, serve para voce criar um
ClienteBean e populá-lo fora do JTable e passar para este
método que vai acrescentar os dados na última linha do JTable
sem que haja a necessidade de se usar o método "setValueAt(...)" */
public void addRow(UsuarioBean bean){
dataset.add(bean);
fireTableDataChanged();
}
/* Este método foi criado por nós para remover uma linha
específica do JTable, de acordo com linha fornecida pelo
parâmetro "int row" */
public void removeRow(int row) {
dataset.remove(row);
fireTableDataChanged();
}
/* Este método criado por nós, acrescenta uma linha em branco
no JTable, caso voce queira inserir dados diretamente no JTable
tem que chamar este método antes. */
public void addEmptyRow(){
dataset.add(new UsuarioBean());
fireTableDataChanged();
}
}
Veja quanta dinamização nós implementamos no AbstractTableModel. Agora basta voce criar um JTable, passando para o seu Model, esta Classe devidamente populada, assim:
List<ClienteBean> listbean = new ArrayList<ClienteBean>();
ClienteBean cbean = new ClienteBean()
cbean.setCod(1);
cbean.setNome("discorpio");
cbean.setIdade(52);
listbean.add(cbean);
cbean = new ClienteBean();
cbean.setCod(2);
cbean.setNome("JFalca");
cbean.setIdade(25);
listbean.add(cbean);
JTable datagrid = new JTable(new ClienteModel(listbean));
// ou
JTable datagrid = new JTable();
datagrid.setModel(new ClienteModel(listbean));
// ou ainda
JTable datagrid = new JTable();
datagrid.setModel(new ClienteModel(new List<ClienteBean>());
ClienteModel model = (ClienteModel)datagrid.getModel();
// e mais tarde
ClienteBean cbean = new ClienteBean()
cbean.setCod(1);
cbean.setNome("discorpio");
cbean.setIdade(52);
model.addRow(cbean);
cbean = new ClienteBean();
cbean.setCod(2);
cbean.setNome("JFalca");
cbean.setIdade(25);
model.addRow(cbean);
Veja só quanto disponibilidade de inserção de dados no seu JTable com AbstractTableModel.
Espero ter esclarecido