Morte definitiva ao default table model

50 respostas
D

gente,

Vamo parar com essa bobeira de usar DefaultTableModel, realmente... eu usei uma vez, o vinny me passou uns links para estudar... Peguei um modelo pronto e comecei a usar... NUNCA mais parei.. então vamos ao passo-a-passo?

PRIMEIRA COISA: você deve criar uma classe no seu projeto para ser a classe do modelo... Para fazer isso, basta você adaptar o seguinte código:

package regra;

import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;

public class ClienteTableModel extends AbstractTableModel {

    private static final long serialVersionUID = 1L;

    /* Lista de Cliente que representam as linhas. */
    private List<Cliente> linhas;

    /* Array de Strings com o nome das colunas. */
    private String[] colunas = new String[]{
        "Nome","Endereço", "Telefone"};



    /* Cria um ClienteTableModel vazio. */
    public ClienteTableModel() {
        linhas = new ArrayList<Cliente>();
    }

    /* Cria um ClienteTableModel carregado com
     * a lista de Cliente especificada. */
    public ClienteTableModel(List<Cliente> listaDeCliente) {
        linhas = new ArrayList<Cliente>(listaDeCliente);
    }


    /* Retorna a quantidade de colunas. */
    @Override
    public int getColumnCount() {
        // Está retornando o tamanho do array "colunas".
        return colunas.length;
    }

    /* Retorna a quantidade de linhas. */
    @Override
    public int getRowCount() {
        // Retorna o tamanho da lista de Cliente.
        return linhas.size();
    }


    @Override
    public String getColumnName(int columnIndex) {
        // Retorna o conteúdo do Array que possui o nome das colunas
        return colunas[columnIndex];
    }

    ;

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return String.class;
    }

    ;


    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
            Cliente cliente = linhas.get(rowIndex);

        // Retorna o campo referente a coluna especificada.
        // Aqui é feito um switch para verificar qual é a coluna
        // e retornar o campo adequado. As colunas sãoas mesmas
        // que foram especificadas no array "colunas".
        switch (columnIndex) {

            // Seguindo o exemplo: "Tipo","Data de Cadastro", "Nome", "Idade"};
            case 0:
                return cliente.getNome();
            case 1:
                return cliente.getEndereco();
            case 2:
                return cliente.getTel();
            default:
                // Isto não deveria acontecer...
                throw new IndexOutOfBoundsException("columnIndex out of bounds");
        }
    }

 @Override
 //modifica na linha e coluna especificada
 public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
      Cliente cliente = linhas.get(rowIndex); // Carrega o item da linha que deve ser modificado

     switch (columnIndex) { // Seta o valor do campo respectivo
         case 0:
             cliente.setNome(aValue.toString());
         case 1:
             cliente.setEndereco(aValue.toString());
         case 2:
             cliente.setTel(aValue.toString());

         default:
             // Isto não deveria acontecer...             
     }
     fireTableCellUpdated(rowIndex, columnIndex);
     }

    //modifica na linha especificada
    public void setValueAt(Cliente aValue, int rowIndex) {
        Cliente cliente = linhas.get(rowIndex); // Carrega o item da linha que deve ser modificado

        cliente.setNome(aValue.getNome());
        cliente.setEndereco(aValue.getEndereco());
        cliente.setTel(aValue.getTel());

        fireTableCellUpdated(rowIndex, 0);
        fireTableCellUpdated(rowIndex, 1);
        fireTableCellUpdated(rowIndex, 2);

    }
    ;


    ;


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


    public Cliente getCliente(int indiceLinha) {
        return linhas.get(indiceLinha);
    }



    /* Adiciona um registro. */
    public void addCliente(Cliente m) {
        // Adiciona o registro.
        linhas.add(m);


        int ultimoIndice = getRowCount() - 1;

        fireTableRowsInserted(ultimoIndice, ultimoIndice);
    }

    /* Remove a linha especificada. */
    public void removeCliente(int indiceLinha) {
        linhas.remove(indiceLinha);

        fireTableRowsDeleted(indiceLinha, indiceLinha);
    }

    /* Adiciona uma lista de Cliente ao final dos registros. */
    public void addListaDeCliente(List<Cliente> cliente) {
        // Pega o tamanho antigo da tabela.
        int tamanhoAntigo = getRowCount();

        // Adiciona os registros.
        linhas.addAll(cliente);

        fireTableRowsInserted(tamanhoAntigo, getRowCount() - 1);
    }

    /* Remove todos os registros. */
    public void limpar() {
        linhas.clear();


        fireTableDataChanged();
    }

    /* Verifica se este table model esta vazio. */
    public boolean isEmpty() {
        return linhas.isEmpty();
    }



}

SEGUNDA COISA: criar um atributo do tipo do modelo na janela em que a jtable existe:

ClientesTableModel modelo;

TERCEIRA COISA: no construtor da janela você vai adicionar o modelo: eis o exemplo:

public Jan_Principal() {
        super("Título da janela");
        initComponents(); 
        setLocationRelativeTo(null); //janela fica no centro da tela ao ficar visível...


        //Adicionando os modelos das tabelas
        modelo = new ClientesTableModel();
        tabela_Exemplo.setModel(modelo);
}

QUARTA COISA: na hora de adicionar algum "Cliente" no caso na tabela basta fazer:

modelo.addClientes(objetoDoCliente);

abraços!
Espero que possa ajudar alguem!

50 Respostas

H

Nunca vai morrer hehehehe

Se tem cara fazendo programa em DOS criando tabela com caracter de || e = ainda, c acha default table model ruim?? huauhahuahuauhhuahauuaha

Sempre tem os defensores inabalaveis contra o default table model, mas ele vai continuar firme e forte hehehehe

Todo newbie vai usar um dia, ta no site da Oracle…

A

Até porque antes de aprender a correr, aprendemos a andar… e antes disso aprendemos a engatinhar

C

Toh usando essa danada no netbeans se alguem tiver alguma coisa pra facilitar as coisas seram muito bem vindas.

P

Eu utilizo o ObjectTableModel do proj Towell, gostei bastante, muito simples de usarr…
segue link: http://code.google.com/p/towel/wiki/ObjectTableModel

M

Também uso a ObjectTableModel do projeto Towel do Marky e recomendo.

E

Seguindo esta analogia, eu diria que o DefaultTableModel representa uma fase antes desta, aquela em que temos que chorar. :lol:

E

Ao d34d_d3v1l, excelente iniciativa abandonar o DefaultTableModel.

Quanto ao model postado, apenas algumas dicas:

O método setValueAt deveria setar o valor de um campo do Cliente, correspondente a célula passada por parâmetro. Ficaria mais ou menos assim:
@Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
         Clientes clientes = linhas.get(rowIndex);; // Carrega o item da linha que deve ser modificado

        switch (columnIndex) { // Seta o valor do campo respectivo
            case 0:
                clientes.setTipo(aValue);
            case 1:
                clientes.setData(aValue);
            case 2:
                clientes.setNome(aValue);
            case 3:
                clientes.setIdade(aValue);
             
            default:  
                // Isto não deveria acontecer...   
                throw new IndexOutOfBoundsException("columnIndex out of bounds");

        fireTableCellUpdated(rowIndex, columnIndex); // Notifica a atualização da célula
    }
Porém, com o método isCellEditable retornando sempre false, ele acabará não sendo usado. E faltou retornar o Cliente no método getCliente:
public Cliente getClientes(int indiceLinha) {
    return linhas.get(indiceLinha);
}
J

comecei a refatorar mru projeto usando as proprias o Table model “Local”, tem um ganho bem significativo com relação ao desempenho da maquina!
a unica coisa que nao consegui resolver é como se pegao registro depois da tabela filtrada…
se alguem souber disso, posta ake tbm
(=

D

Eric Yuzo obrigado, já fiz as mudanças necessárias :wink:

Realmente gente, concordo… Sempre haverá quem está no começo vai usar o DefaultTableModel… mas a intenção é que eles larguem de usá-lo ao ver este tópico… :slight_smile:

D

dei uma modificada no tableModel,

coloquei um mais recente e criei um novo método para modificar os dados de uma linha…
Abraços!

A

posta o codigo ae pra nois ver como ficou! se possivel! valeuuu!!!

V

Na verdade, isso é conversa para boi dormir.

Eu atendo o tópico de Java Básico e Interface Gráfica no GUJ há pelo menos 5 anos (se não for mais do que isso). Desde lá, vejo muitos iniciantes gastando horas para realizar operações como remover registros, sincronizar o Default com dados do banco ou mesmo replicar buscas. Tarefas que o DefaultTableModel torna difíceis e enfadonhas.

Entretanto, a maioria se apavora só de olhar para um TableModel, só por achar o código mais complicado. A maioria, refuta o estudo antes mesmo de começar. Não sei se por medo ou por preguiça.

O que o povo não percebe é que o código do TableModel personalizado é tudo o que se precisa para fazer uma tabela editável. E, se o sujeito parar para entender, vai ver que as implementações dos métodos são efetivamente triviais. Na interface gráfica, os códigos de botões, que usam um model personalizado, ficam extremamente ridículos. De fato, se você pegar todo o código que o DefaultTableModel deixou espalhado nos vários métodos de botão, vai ver que você gastou muito mais linhas, tempo e esforço em operações que, num model de verdade, nem sequer existiriam.

O único iniciante que realmente pode usar essa desculpa é aquele que ainda nem sequer sabe modelar classes de negócio. É o caso de alguns que aparecem por aqui, colocando resultados de consultas diretamente em tabelas, no bom e velho estilo das linguagens estruturadas. Mas não são todos, e também não são a maioria. O que realmente me impressiona é que muita gente que está disposta a entender o modelo MVC, Hibernate e que em web usariam um design elegante, ainda que complexo, foge do TableModel personalizado quando vai para o Desktop. Vai entender.

C

Meus prezados, bom dia

Quero usar jtableModel corretamente, por isso estou estudando a fundo toda a classe do link http://www.guj.com.br/java/231928-morte-definitiva-ao-default-table-model. Mas eis a minha dúvida

onde diz List<Cliente> linhas; eu sei que se trata de um objeto. Porém não sei que objeto é esse. é uma classe ? um resultado de consulta SQL ?

o que eu faço ? com essa linha ? (desde já perdoe a minha ignorância e muito obrigado!)

Alguem poderia esclarecer pra mim o que é e se for pra receber um objeto do tipo ResultSet como faço para enviar para essa classe ?

/* Lista de Cliente que representam as linhas.*/
 private List<Cliente> linhas;
V

É uma classe que contém os dados dos clientes. Imagine que essa lista em algum momento foi carregada do banco, por algum DAO.

C

OK.
Vejá só, carrego os dados, do BD e seto os os valores para os campos, para uma tabela que seja e tal. certo !
usando os comandos while(rs.next())…etc

Ou seja: não consigo entender como eu irei escrever a classe Cliente de forma que ela me retorne a lista ou Linhas desejadas.

segue a baixo uma classe comum que eu uso normalmente, só não sei como fazer com que essa classe faça parte do atributo private List&lt;Cliente&gt; linhas; .

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package minhasClasses;

import java.sql.SQLException;
import javax.swing.JOptionPane;


/**
 *
 * @author CESMT-CPD
 */
public class clsManut_Cadastro {
    
    private RegNegocio rn;
   
    private String txtCPF;
    private String txtCodigo;
    private String txtDN;
    private String txtDTpericia;
    private String txtEnde;
    private String txtHorario;
    private String txtNIS;
    private String txtNome;
    private String txtNomeMae;
    private String txtNomePai;
    private String txtObs;
    private String txtRG;
    private String txtAnoBase;
    private String txtDT_Lancamento;
        
     /**
     * @return the txtCPF
     */
    public String getTxtCPF() {
        return txtCPF;
    }

   
   
    /*Final dos ATRIBUTOS*/

    /**
     * @param txtCPF the txtCPF to set
     */
    public void setTxtCPF(String txtCPF) {
        this.txtCPF = txtCPF;
    }

    /**
     * @return the txtCodigo
     */
    public String getTxtCodigo() {
        return txtCodigo;
    }

    /**
     * @param txtCodigo the txtCodigo to set
     */
    public void setTxtCodigo(String txtCodigo) {
        this.txtCodigo = txtCodigo;
    }

    /**
     * @return the txtDN
     */
    public String getTxtDN() {
        return txtDN;
    }

    /**
     * @param txtDN the txtDN to set
     */
    public void setTxtDN(String txtDN) {
        this.txtDN = txtDN;
    }

    /**
     * @return the txtDTpericia
     */
    public String getTxtDTpericia() {
        return txtDTpericia;
    }

    /**
     * @param txtDTpericia the txtDTpericia to set
     */
    public void setTxtDTpericia(String txtDTpericia) {
        this.txtDTpericia = txtDTpericia;
    }

    /**
     * @return the txtEnde
     */
    public String getTxtEnde() {
        return txtEnde;
    }

    /**
     * @param txtEnde the txtEnde to set
     */
    public void setTxtEnde(String txtEnde) {
        this.txtEnde = txtEnde;
    }

    /**
     * @return the txtHorario
     */
    public String getTxtHorario() {
        return txtHorario;
    }

    /**
     * @param txtHorario the txtHorario to set
     */
    public void setTxtHorario(String txtHorario) {
        this.txtHorario = txtHorario;
    }

    /**
     * @return the txtNIT
     */
    public String getTxtNIS() {
        return txtNIS;
    }

    /**
     * @param txtNIT the txtNIT to set
     */
    public void setTxtNIS(String txtNIS) {
        this.txtNIS = txtNIS;
    }

    /**
     * @return the txtNome
     */
    public String getTxtNome() {
        return txtNome;
    }

    /**
     * @param txtNome the txtNome to set
     */
    public void setTxtNome(String txtNome) {
        this.txtNome = txtNome;
    }

    /**
     * @return the txtNomeMae
     */
    public String getTxtNomeMae() {
        return txtNomeMae;
    }

    /**
     * @param txtNomeMae the txtNomeMae to set
     */
    public void setTxtNomeMae(String txtNomeMae) {
        this.txtNomeMae = txtNomeMae;
    }

    /**
     * @return the txtNomePai
     */
    public String getTxtNomePai() {
        return txtNomePai;
    }

    /**
     * @param txtNomePai the txtNomePai to set
     */
    public void setTxtNomePai(String txtNomePai) {
        this.txtNomePai = txtNomePai;
    }

    /**
     * @return the txtObs
     */
    public String getTxtObs() {
        return txtObs;
    }

    /**
     * @param txtObs the txtObs to set
     */
    public void setTxtObs(String txtObs) {
        this.txtObs = txtObs;
    }

    /**
     * @return the txtRG
     */
    public String getTxtRG() {
        return txtRG;
    }

    /**
     * @param txtRG the txtRG to set
     */
    public void setTxtRG(String txtRG) {
        this.txtRG = txtRG;
    }

    /**
     * @return the txtAnoBase
     */
    public String getTxtAnoBase() {
        return txtAnoBase;
    }

    /**
     * @param txtAnoBase the txtAnoBase to set
     */
    public void setTxtAnoBase(String txtAnoBase) {
        this.txtAnoBase = txtAnoBase;
    }

    /**
     * @return the txtDT_Lancamento
     */
    public String getTxtDT_Lancamento() {
        return txtDT_Lancamento;
    }

    /**
     * @param txtDT_Lancamento the txtDT_Lancamento to set
     */
    public void setTxtDT_Lancamento(String txtDT_Lancamento) {
        this.txtDT_Lancamento = txtDT_Lancamento;
    }
    
    
    //CONSTRUTOR ******************************
    public clsManut_Cadastro(){
      rn = new RegNegocio();
      rn.Conecta();
    }//construtor
          
    
    public void exeInsere(){
       try{
        rn.execUpIns("INSERT INTO dbRais("
                + "nome,"
                + "nomMae,"
                + "nomPai,"
                + "DatNasc,"
                + "cpf,"
                + "rg,"
                + "Enderec,"
                + "numNIS,"
                + "numCodigo,"
                + "Dt_Pericia,"
                + "horario,"
                + "obs,"
                + "AnoBase,"
                + "DT_lancamento)VALUES('"
                +getTxtNome()+"','"
                +getTxtNomeMae()+"','"
                +getTxtNomePai()+"','"
                +getTxtDN()+"','" 
                +getTxtCPF()+"','"
                +getTxtRG()+"','"
                +getTxtEnde()+"','"
                +getTxtNIS()+"','"
                +getTxtCodigo()+"','"
                +getTxtDTpericia()+"','"
                +getTxtHorario()+"','"
                +getTxtObs()+"','"
                +getTxtAnoBase()+"','"
                +getTxtDT_Lancamento()+"')");
        
        rn.Desconecta();
       }catch(SQLException e2)
       {
          JOptionPane.showMessageDialog(null, "Erro ao tentar inserir esse registro. O erri diz:! "+e2);
       }
    }//final do método para inserir
    
    
//tratamento do campo CPF
public String tiraCaract(String campo){

    String pCPF = campo;
    String sCPF = pCPF.replace(".", "");
    String tCPF = sCPF.replace("-", "");
 return tCPF;
}   //final do método tiraCaract



 public void exeUpdate(String pCPF) throws SQLException{
     //  try{
        rn.execUpIns("execute procedure insmanutcad('"
                +pCPF+"','"
                +getTxtNome()+"','"
                +getTxtNomeMae()+"','"
                +getTxtNomePai()+"','"
                +getTxtDN()+"','" 
                +getTxtCPF()+"','"
                +getTxtRG()+"','"
                +getTxtEnde()+"','"
                +getTxtNIS()+"','"
                +getTxtCodigo()+"','"
                +getTxtDTpericia()+"','"
                +getTxtHorario()+"','"
                +getTxtObs()+"')");
        rn.Desconecta();
    }//final do método para inserir


 public void exeCarregarDados(String pCPF){
       try{
        rn.execQuery("select * from dbRais where cpf = "+pCPF);
            while(rn.rs.next()) { 
                setTxtNome(rn.rs.getString("NOME"));
                setTxtNomeMae(rn.rs.getString("NOMMAE"));
                setTxtNomePai(rn.rs.getString("NOMPAI"));
                setTxtDN(rn.rs.getString("DATNASC"));
                setTxtCPF(rn.rs.getString("CPF"));
                setTxtRG(rn.rs.getString("RG"));
                setTxtEnde(rn.rs.getString("ENDEREC"));
                setTxtNIS(rn.rs.getString("NUMNIS"));
                setTxtCodigo(rn.rs.getString("NUMCODIGO"));
                setTxtDTpericia(rn.rs.getString("DT_PERICIA"));
                setTxtHorario(rn.rs.getString("HORARIO"));
                setTxtObs(rn.rs.getString("OBS"));
                setTxtAnoBase(rn.rs.getString("ANOBASE"));
          }
        rn.Desconecta();
       }catch(Exception e)
       {
          JOptionPane.showMessageDialog(null, "Erro ao Carregar os dados! "
                  + "Linha 313 - Mpublic void exeCarregarDados(String pCPF). \n"
                  + "Verifique se há um registro selecionado.");
       }
    }//final do método para inserir
 

public void execDelete(String pCPF ){
    try{
    rn.execUpIns("delete from dbRais where cpf="+pCPF);
    JOptionPane.showMessageDialog(null, "Dados excluídos com sucesso!");
    }catch(SQLException e){
       JOptionPane.showMessageDialog(null, "Erro ao tentar excluir o registro! O erro diz: "+e);
    }
}//final do método excluir


}//final da classe clsTeste
V

No caso caso, seu model teria um List<clsManut_Cadastro> no lugar de um List<Cliente>

A classe Cliente nesse caso foi só usada de exemplo, mas vc pode criar um model para qualquer coisa.

Se você quer carregar um Table, você vai carregar uma lista de algum tipo de dados, não?

C

ViniGodoy:
No caso caso, seu model teria um List<clsManut_Cadastro> no lugar de um List<Cliente>

A classe Cliente nesse caso foi só usada de exemplo, mas vc pode criar um model para qualquer coisa.

Se você quer carregar um Table, você vai carregar uma lista de algum tipo de dados, não?

Certo, mas em que momento da minha classe clsManut_Cadastro, o modelo irá entender que meu Jtable deverá ser carregado com os dados do DB?
pois essa classe contem “n” métodos e eu ainda não entendir como essa mágica é feita dentro da classe do modelo.

Mais uma vez perdão pela ignorânica. é que preciso apenas entender mesmo todos os detalhes e pelo jeito, vc aqui é autoridade máxima. obrigado !

C

cleber_prog:
ViniGodoy:
No caso caso, seu model teria um List<clsManut_Cadastro> no lugar de um List<Cliente>

A classe Cliente nesse caso foi só usada de exemplo, mas vc pode criar um model para qualquer coisa.

Se você quer carregar um Table, você vai carregar uma lista de algum tipo de dados, não?

Certo, mas em que momento da minha classe clsManut_Cadastro, o modelo irá entender que meu Jtable deverá ser carregado com os dados do DB?
pois essa classe contem “n” métodos e eu ainda não entendir como essa mágica é feita dentro da classe do modelo.

Mais uma vez perdão pela ignorânica. é que preciso apenas entender mesmo todos os detalhes e pelo jeito, vc aqui é autoridade máxima. obrigado !

depois de substituir Cliente pela minha classe supracitada deu o seguinte erro em getRowCount():

/* Retorna a quantidade de linhas. */
    @Override
    public int getRowCount() {
        // Retorna o tamanho da lista de Cliente.
        return linhas.size();
    }
run:
Exception in thread "main" java.lang.NullPointerException
	at minhasClasses.clsConfigJtable.getRowCount(clsConfigJtable.java:53)
	at javax.swing.JTable.getRowCount(JTable.java:2631)
	at javax.swing.plaf.basic.BasicTableUI.createTableSize(BasicTableUI.java:1646)
	at javax.swing.plaf.basic.BasicTableUI.getPreferredSize(BasicTableUI.java:1687)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1634)
	at javax.swing.JViewport.getViewSize(JViewport.java:1018)
	at javax.swing.ScrollPaneLayout.preferredLayoutSize(ScrollPaneLayout.java:476)
	at java.awt.Container.preferredSize(Container.java:1599)
	at java.awt.Container.getPreferredSize(Container.java:1584)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1636)
	at org.netbeans.lib.awtextra.AbsoluteLayout.layoutContainer(Unknown Source)
	at java.awt.Container.layout(Container.java:1421)
	at java.awt.Container.doLayout(Container.java:1410)
	at java.awt.Container.validateTree(Container.java:1507)
	at java.awt.Container.validateTree(Container.java:1513)
	at java.awt.Container.validateTree(Container.java:1513)
	at java.awt.Container.validateTree(Container.java:1513)
	at java.awt.Container.validate(Container.java:1480)
	at java.awt.Window.show(Window.java:861)
	at java.awt.Component.show(Component.java:1563)
	at java.awt.Component.setVisible(Component.java:1515)
	at java.awt.Window.setVisible(Window.java:842)
	at prjprincipal.Main.main(Main.java:31)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at minhasClasses.clsConfigJtable.getRowCount(clsConfigJtable.java:53)
	at javax.swing.JTable.getRowCount(JTable.java:2631)
	at javax.swing.plaf.basic.BasicTableUI.createTableSize(BasicTableUI.java:1646)
	at javax.swing.plaf.basic.BasicTableUI.getPreferredSize(BasicTableUI.java:1687)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1634)
	at javax.swing.JViewport.getViewSize(JViewport.java:1018)
	at javax.swing.ScrollPaneLayout.preferredLayoutSize(ScrollPaneLayout.java:476)
	at java.awt.Container.preferredSize(Container.java:1599)
	at java.awt.Container.getPreferredSize(Container.java:1584)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1636)
	at org.netbeans.lib.awtextra.AbsoluteLayout.layoutContainer(Unknown Source)
	at java.awt.Container.layout(Container.java:1421)
	at java.awt.Container.doLayout(Container.java:1410)
	at java.awt.Container.validateTree(Container.java:1507)
	at java.awt.Container.validateTree(Container.java:1513)
	at java.awt.Container.validateTree(Container.java:1513)
	at java.awt.Container.validateTree(Container.java:1513)
	at java.awt.Container.validate(Container.java:1480)
	at java.awt.Window.dispatchEventImpl(Window.java:2476)
	at java.awt.Component.dispatchEvent(Component.java:4460)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at minhasClasses.clsConfigJtable.getRowCount(clsConfigJtable.java:53)
	at javax.swing.JTable.getRowCount(JTable.java:2631)
	at javax.swing.plaf.basic.BasicTableUI.createTableSize(BasicTableUI.java:1646)
	at javax.swing.plaf.basic.BasicTableUI.getPreferredSize(BasicTableUI.java:1687)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1634)
	at javax.swing.JViewport.getViewSize(JViewport.java:1018)
	at javax.swing.ScrollPaneLayout.preferredLayoutSize(ScrollPaneLayout.java:476)
	at java.awt.Container.preferredSize(Container.java:1599)
	at java.awt.Container.getPreferredSize(Container.java:1584)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1636)
	at org.netbeans.lib.awtextra.AbsoluteLayout.layoutContainer(Unknown Source)
	at java.awt.Container.layout(Container.java:1421)
	at java.awt.Container.doLayout(Container.java:1410)
	at java.awt.Container.validateTree(Container.java:1507)
	at java.awt.Container.validateTree(Container.java:1513)
	at java.awt.Container.validateTree(Container.java:1513)
	at java.awt.Container.validateTree(Container.java:1513)
	at java.awt.Container.validate(Container.java:1480)
	at java.awt.Window.dispatchEventImpl(Window.java:2476)
	at java.awt.Component.dispatchEvent(Component.java:4460)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
C

Prezados, para nós que estamos aprendendo, pelo menos para mim, o tópico do amigo d34d_d3v1! que fala sobre a “Morte definitiva ao default table model” é execelente. Porém, depois de seguir todos os passos, buscar estudar as classes pertinentes. Ainda ficaram lacunas para serem preenchidas e meu projeto teste de estudos simplesmente não compila/traduz. (erro já mencionado acima).

Há uma campanha fortissima contra o tal default table model, eu sou a favor da campanha, pois se é para programa, que seja da forma correta, então eu fico buscando essas formas e estudando-as, com base nos temas nos foruns debatidos.

Mas vejam só, eu estou a 6 horas tentando fazer a classe TableModel funcionar, tudo que preciso é apenas setar os dados de DB em um Jtable, isso tudo claro, estudando para aprender.

Cheguei no meu objetivo usando o tal default table model em 15min, sem contar a pausa para o cafezinho!!

Quero programar da forma correta. Mas vamos combinar, pega uma classe aqui, para estudar, se matar desvendando seus mistérios pra no final das contas descobrir que ela foi feita pra não funcionar é dose!!

Ou seja: default table model enquanto dure !

V

Você inicializou a lista de linhas? Pq NullPointerException tem um significado bem claro: que ela não foi inicializada. Você deve carregar a lista do banco, e então repassar a lista para seu tablemodel, caso contrário, não funciona mesmo.

Desenhar a tabela é o menor dos problemas. Quando você começar a manter um DefaultTableModel editável, ou precisar personalizar sua tabela com colunas ordenáveis, totais, ícones ou cores ou mesmo ter a coluna de ID escondida, aí conversamos melhor. Todos são problemas incríveis no Default, que são naturalmente resolvidos no seu próprio TableModel.

Além disso, na minha assinatura, tem um link para diversas implementações funcionais de TableModel. Dê uma olhada nessa do Eric:
http://www.guj.com.br/java/225793-exemplo-de-tablemodel#1156821

Vencer a curva de aprendizado é parte do processo. O fato de você perder 1 ou 2 dias aprendendo a usar uma ferramenta da forma correta não é desculpa ou justificativa para permanecer por anos dando murro em ponta de faca da forma incorreta, mesmo que a forma incorreta aparente ser mais fácil. Você vai, sim, perder algumas horas aprendendo a organizar seu projeto de maneira adequada, mas vai ganhar anos de manutenção tranquila.

C

Vlw parceiro !!
Rs. concordo plenamente contigo. Mas eu sei no fundo que vc teve seus momentos de stress também, por não conseguir ali naquele momento. Mas sei bem do que vc está falando quando diz perder horas estudadndo… !!

Vou verificar sua orientação.
Mas fique certo, meu único objetivo é realmente fazer da forma certa minhas aplicações, pois é algo que amo muito fazer e se amo, tem que ser do jeito certo.

Ah… e vc ainda verá muitos post meus aqui…rs

Mais uma vez muito obrigado.
amigo certa vez me disseram, o GUJ é o melhor lugar para se está, quando se pretende aprender/aprimorar JAVA. Hoje sei por que !!

Vlw muito obrigado !! vamos a luta… ufa lá vai eu mais algumas horas ou dias… sei lá…

C

Tem como vcs passarem pra mim um exemplo de como
iniciar a lista com dados do DB e essa ser usada na classe TableModel a baixo?

C

Meus Mestre, coloca esse código em uma lista pra mim

try{ 
   rn.execQuery("select * from dbRais");
     while(rn.rs.next()) { 
           mc.setTxtNome(rn.rs.getString("nome"));
           mc.setTxtRG(rn.rs.getString("rg"));
           mc.setTxtCPF(rn.rs.getString("cpf"));
           mc.setTxtNIS(rn.rs.getString("numNIS"));
           mc.setTxtAnoBase(rn.rs.getString("anobase"));
     }
        }catch(SQLException e){
          JOptionPane.showMessageDialog(null, e);
          }

já entendi o TableModel, agora quero mandar uma Lista de dados pra ele!!

B

d34d_d3v1l

Obrigado pelo tutorial cara, eu estava mesmo procurando.

Ficou tão bem explicado que consegui fazer funcionar em questão de minutos, sem contar que irá resolver muitos de meus problemas utilizando tabelas.

Abraços.

P

Muito bom o tutorial, também fiz funcionar aqui…

mas deixa eu ver se entendi, quer dizer que eu terei que fazer uma TableModel para cada novo grid?
não tem como deixar isso mais genérico?

digo isso pelo seguinte, eu estava usando Default Table Model e uma coisa que gostei foi a possibilidade de caso as dimensões da minha tabela mudem ele se adapta… para entender melhor, estou lendo as informações dessas tabelas de um arquivo XML que eh retornado por um Web Service… não eh só isso que o WS retorna, mas eh um dos casos… e ele pode retornar entre várias tabelas diferentes, com dimensões diferentes… o que eu fazia era ler esse XML, primeiramente os campos (colunas) e depois os dados (linhas)… isso está separado por duas TAGs uma e uma então isso pra minha implementação eh indiferente as dimensões da tabela/grid…

esses dados do XML era lidos para um vetor (colunas) e uma matriz (dados)… e aí eu passava isso para o Default Table Model dessa forma:

DefaultTableModel modelo = new DefaultTableModel(dados, colunas); // dados eh uma matriz (String[][]) - e colunas um vetor (String[])
JTable tabela = new JTable(modelo);

por isso não consegui entender direito a vantagem em usar uma TableModel própria ou a desvantagem de usar uma DTM no meu caso… alguém pode me explicar melhor qual seria a real vantagem para mim e como eu resolveria o problema de ter que criar um TableModel para cada grid diferente que eu tiver… são muuuuuitos grid diferentes que retornam do WS…

agradeço a atenção…

P

ninguém?

M

Voce pode criar um TableModel generico ou usar um como o ObjectTableModel.

L

Vini…é bem isso mesmo! Com os exemplos que tem aqui no GUJ só não aprende que ta com preguiça!! :lol:

R

Boa tarde pessoal, alguém tem algum exemplo de como fazer a classe Cliente?

Sou iniciante e gostaria de começar trabalhando com o modo certo.

D

fazer a classe cliente?

estude OO cara :slight_smile:
caelum tem uma apostila boa

abrazz

R

Já estou lendo ela, só que enquanto estudo a teoria eu estou vendo um pouco de parte prática, senão não entra na minha cabeça xD.

Eu dei uma estudada na classe e já entendi melhor ela, o que eu preciso fazer agora é colocar as informações que tenho no banco de dados na tabela através de um ResultSet.

B

Nessa parte do TableModel, é bom que você entenda encapsulamento antes de tentar implementar, pois mais que você ja queira praticar, entender esse conceito é essencial.

Fique a vontade para perguntar :slight_smile:

L

Implementei meu próprio TableModel para o meu JTable e funcionou que é uma beleza, muito obrigado pelos exemplos de TableModel. :lol:
Mas, pessoal, e com relação a JComboBox, é legal usar o DefaultComboBoxModel ou tem um modo de implementar um modelo customizado? :shock:
Obrigado. :slight_smile:

L

Leandro Rocha:
Implementei meu próprio TableModel para o meu JTable e funcionou que é uma beleza, muito obrigado pelos exemplos de TableModel. :lol:
Mas, pessoal, e com relação a JComboBox, é legal usar o DefaultComboBoxModel ou tem um modo de implementar um modelo customizado? :shock:
Obrigado. :slight_smile:

Legal esse modelo, vou testar: http://www.guj.com.br/java/263090-resolvidojcombobox-com-implementacao-de-comboboxmodel

L

Alguém tem mais alguma alternativa para o ComboBoxModel?
Legal: http://www.java2s.com/Tutorial/Java/0240__Swing/JComboBoxUsingtheCustomModel.htm
Vlw :slight_smile:

A

olá ViniGodoy, tem com vc me da uma ajudinha com os metodos da tablemodel

ViniGodoy:
Você inicializou a lista de linhas? Pq NullPointerException tem um significado bem claro: que ela não foi inicializada. Você deve carregar a lista do banco, e então repassar a lista para seu tablemodel, caso contrário, não funciona mesmo.

Desenhar a tabela é o menor dos problemas. Quando você começar a manter um DefaultTableModel editável, ou precisar personalizar sua tabela com colunas ordenáveis, totais, ícones ou cores ou mesmo ter a coluna de ID escondida, aí conversamos melhor. Todos são problemas incríveis no Default, que são naturalmente resolvidos no seu próprio TableModel.

Além disso, na minha assinatura, tem um link para diversas implementações funcionais de TableModel. Dê uma olhada nessa do Eric:
http://www.guj.com.br/java/225793-exemplo-de-tablemodel#1156821

Vencer a curva de aprendizado é parte do processo. O fato de você perder 1 ou 2 dias aprendendo a usar uma ferramenta da forma correta não é desculpa ou justificativa para permanecer por anos dando murro em ponta de faca da forma incorreta, mesmo que a forma incorreta aparente ser mais fácil. Você vai, sim, perder algumas horas aprendendo a organizar seu projeto de maneira adequada, mas vai ganhar anos de manutenção tranquila.

J

Mas o mais recomendado é criar um modelo pra cada Classe mesmo? não tem uma genérica?
Agradeço desde já

V

JavaS:
Mas o mais recomendado é criar um modelo pra cada Classe mesmo? não tem uma genérica?
Agradeço desde já

B

para usar o AbstractTableModel corretamente eu vou ter que ter uma classe para cada entidade
por exemplo:

ClienteTableModel
FuncionarioTableModel
PedidoTableModel

e assim por diante

V

Sim.

L

Imagina que eu tenho um resultset e já quero inicicia-lo na tabela:

Eu tenho minha classe assim:

import java.sql.SQLException;
import java.util.ArrayList;
	import java.util.List;
import javax.swing.table.AbstractTableModel;

	public class ModeloTabela extends AbstractTableModel {
		
		private static final long serialVersionUID = 1L;
		DAO DAO = new DAO();
		
		private String[] colunas = {"ID Componente", "Componente", "Servidor de Origem", "Servidor de Destino", "Alias do Componente", "Ordem de Origem", "Ordem de Destino"};
		

		/* Lista de Sócios que representam as resultado. */
		private List<InfraBridge> resultado;
		
		public ModeloTabela() throws SQLException {
			resultado = DAO.consulta();
		}


		/* Retorna a quantidade de colunas. */
		@Override
		public int getColumnCount() {
			// Está retornando o tamanho do array "colunas".
			// Mas como o array é fixo, vai sempre retornar 4.
			return colunas.length;
		}

		/* Retorna a quantidade de resultado. */
		@Override
		public int getRowCount() {
			// Retorna o tamanho da lista de sócios.
			return resultado.size();
		}

		/* Retorna o nome da coluna no índice especificado.
		 * Este método é usado pela JTable para saber o texto do cabeçalho. */
		@Override
		public String getColumnName(int columnIndex) {
			// Retorna o conteúdo do Array que possui o nome das colunas
			// no índice especificado.
			return colunas[columnIndex];
		};

		/* Retorna a classe dos elementos da coluna especificada.
		 * Este método é usado pela JTable na hora de definir o editor da célula. */
		@Override
		public Class<?> getColumnClass(int columnIndex) {
			// Retorna a classe referente a coluna especificada.
			// Aqui é feito um switch para verificar qual é a coluna
			// e retornar o tipo adequado. As colunas são as mesmas
			// que foram especificadas no array "colunas".
			switch (columnIndex) {
			case 0: // Primeira coluna é o nome, que é uma String.
				return int.class;
			case 1: // Segunda coluna é o telefone, que também é uma String..
				return String.class;
			case 2: // Terceira coluna é a data de cadastro,
					// apesar de ser do tipo Calendar,
					// estou retornando Date por causa da formatação.
				return String.class;
			case 3: // Quarta coluna é a mensalidade, um double.
				return String.class;
			case 4: // Quarta coluna é a mensalidade, um double.
				return String.class;
			case 5: // Quarta coluna é a mensalidade, um double.
				return int.class;
			case 6: // Quarta coluna é a mensalidade, um double.
				return int.class;
			default:
				// Se o índice da coluna não for válido, lança um
				// IndexOutOfBoundsException (Exceção de índice fora dos limites).
				// Não foi necessário verificar se o índice da linha é inválido,
				// pois o próprio ArrayList lança a exceção caso seja inválido.
				throw new IndexOutOfBoundsException("columnIndex out of bounds");
			}
		}

		/* Retorna o valor da célula especificada
		 * pelos índices da linha e da coluna. */
		@Override
		public Object getValueAt(int rowIndex, int columnIndex) {
			// Pega o sócio da linha especificada.
			InfraBridge infraBridge = resultado.get(rowIndex);

			// Retorna o campo referente a coluna especificada.
			// Aqui é feito um switch para verificar qual é a coluna
			// e retornar o campo adequado. As colunas são as mesmas
			// que foram especificadas no array "colunas".
			switch (columnIndex) {
			case 0: // Primeira coluna é o nome.
				return infraBridge.getidComponente();
			case 1: // Segunda coluna é o telefone.
				return infraBridge.getComponente();
			case 2: // Terceira coluna é a data de cadastro.
				return infraBridge.getServidorOrigem();
			case 3: // Quarta coluna é a mensalidade.
				return infraBridge.getServidorDestino();
			case 4: // Quarta coluna é a mensalidade.
				return infraBridge.getAliasComponente();
			case 5: // Quarta coluna é a mensalidade.
				return infraBridge.getOrdem1();
			case 6: // Quarta coluna é a mensalidade.
				return infraBridge.getOrdem2();
			default:
				// Se o índice da coluna não for válido, lança um
				// IndexOutOfBoundsException (Exceção de índice fora dos limites).
				// Não foi necessário verificar se o índice da linha é inválido,
				// pois o próprio ArrayList lança a exceção caso seja inválido.
				throw new IndexOutOfBoundsException("columnIndex out of bounds");
			}
		}

		
	}

Está errado???

M

Seu TableModel não deve ser responsavel por consultar dados no banco de dados. Prefira trabalahr com listas e o resultado poderá vir de qualquer lugar.

R

Olá pessoal, estou tentando utilizar o AbstractTableModel, porém, estou com problemas ao inserir um dado na tabela. Ela não está atualizando.

Bom na janela onde fica a tabela eu chamo a tela de inserção:
InserirMarcaGui im = new InserirMarcaGui();
        im.setVisible(true);
Na tela de inserção botão salvar:
private void botaoSalvarActionPerformed(java.awt.event.ActionEvent evt) {                                            
        Marca m = new Marca();
        if (txNome.getText().length() > 0) {
            m.setNome(txNome.getText());
            MarcaTableModel mtb = new MarcaTableModel();
            mtb.addMarca(m);
            MarcaController mc = new MarcaController();
            mc.cadastrar(m);

            dispose();


        }
    }

Não consigo encontrar o erro. Está salvando no banco de dados. Porém a tabela não atualiza. Tenho que fechar a janela para visualizar a modificação.

Pessoal, já consegui resolver.

M

Você está criando um model novo, atualize o já existente.

if (txNome.getText().length() > 0) {  
        m.setNome(txNome.getText());  
        MarcaTableModel mtb = jTable.getModel();  
        mtb.addMarca(m);  
        mtb.notifyDataSetChanged();
        MarcaController mc = new MarcaController();  
        mc.cadastrar(m);  
  
        dispose();  
  
  
    }
R

É Marky.Vasconcelos perdi um tempão por um erro tão besta. Mas já está tudo ok.

Obrigada pela ajuda.

F

Caramba já havia estudado DefaultTableModel e não consegui implementar mas agora com esse tópico consegui implementar a tabela do jeito certo. obrigado

P

Muito mais fácil criar o seu próprio tableModel.

Eu o tenho usado como um classe intermediária entre o a minha BO e a swing. Está certo usá-la desse jeito?
E se eu quiser que no meu JTable apareça menos campos do que tem na minha tabela? por exemplo:

Tabela: PKID_CODIGO, VALOR, DESCRICAO, FKID_ITEM, FKID_GRUPO, FKID_CONTA

e no meu JTable eu só quero que apareça: DESCRICAO, VALOR E FKID_ITEM.

como seria isso? é possível?

2

Como posso usar um TableModel personalizado com uma JList?

V
Não é tão simples, e nem envolve necessariamente o TableModel personalizado.

a) Preencher um JList com os valores possíveis da coluna;

b) Criar um TableCellEditor que trabalhe com o List;

c) Associar o TableCellEditor a coluna em questão.

Leia mais em: http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#editrender

2

Vou dar uma analisada na documentacao
Muito obrigado pela atencao

Criado 2 de fevereiro de 2011
Ultima resposta 31 de jul. de 2014
Respostas 50
Participantes 25