Exemplo de uso TableModel

19 respostas
C

Pessoal, li inúmeros artigos sobre "Cria sua TableModel". E estou quebrando a cabeça com o Default estão,gostaria de saber se a minha classe TableModel está correta, e como faço para lista informações na minha table com dados vindo de uma consulta.

Minha TableModel ( Não fiz nenhum metodo para manipular ainda, seria a principio apenas lista a JTABLE):

public class EstoqueTableModel extends AbstractTableModel{

    private List estoque;

    public EstoqueTableModel() {
        estoque = new ArrayList();
    }

    public EstoqueTableModel(List lista) {
        this();
        estoque.addAll(lista);
    }

    public int getRowCount() {
       
        return estoque.size();
    }

    public int getColumnCount() {
       
        return 6;
    }

    @Override
    public String getColumnName(int column) {
        //qual o nome da coluna
        switch (column){
                 case 0:
                return "Nome";
                 case 1:
                return "Obs";
                 case 2:
                return "Qnt";
                 case 3:
                return "V_Compra";
                 case 4:
                return "V_Venda";
                 case 5:
                return "Lucro";
            default:
        return "";
    }
    }

    @Override
    public Class getColumnClass(int coluna) {
        //Retorna todas as colunas
        return String.class;
    }

    public Object getValueAt(int linha, int coluna) {
     
       Estoque e = (Estoque) estoque.get(linha);
       switch (coluna){
           case 0:
           e.getNome();
           case 1:
           e.getObs();
           case 2:
           e.getObs();
           case 3:
           e.getVCompra();
           case 4:
           e.getVVenda();
           case 5:
           e.getLucro();
           default:
        return "";
    }
    }
    @Override
    public void setValueAt(Object valor, int linha, int coluna) {
       
        Estoque e = (Estoque) estoque.get(linha);
        switch(coluna){
            
           case 0:
           e.setNome(valor.toString());
           break;

           case 1:
           e.setQnt(valor.toString());
           break;

           case 2:
            e.setObs(valor.toString());
           break;

           case 3:
            e.setVCompra(valor.toString());
           break;

           case 4:
            e.setVVenda(valor.toString());
           break;

           case 5:
          e.setLucro(valor.toString());
           break;

        }

       
        fireTableDataChanged();
    }

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

}


}
Minha Lista de Dados:
Public List<Estoque> getLista() throws SQLException {
        String sql = "Select * from estoque";
        PreparedStatement stmt = conexao.prepareStatement(sql);

        ResultSet rs = stmt.executeQuery();

        List<Estoque> minhaLista = new ArrayList<Estoque>();

        while (rs.next()) {

            Estoque e =  new Estoque();
            e.setNome(rs.getString("Nome"));
            e.setObs(rs.getString("Obs"));
            e.setQnt(rs.getString("Qnt"));
            e.setVCompra(rs.getString("V_Compra"));
            e.setVVenda(rs.getString("V_Venda"));
            e.setLucro(rs.getString("Lucro"));

            minhaLista.add(e);
        }
        rs.close();
        stmt.close();

        return minhaLista;

    }

Agora como ficaria um metodo para listar os dados na minha jTable?

19 Respostas

Marky.Vasconcelos
EstoqueTableModel model = new EstoqueTableModel(seuDAO.getLista());
JTable table = new JTable(model);
//Adiciona table em algum lugar

E pronto

C

Então eu fiz esse metodo , quando ilinicializa aparece todos os campos com os nomes nas colunas, mas não aparece nenhum Item.

Ex: tenho 2 itens no meu banco.

aparece o linhas vazias.

public void lista() throws SQLException{
    ManipulaBD m = new ManipulaBD();

    model = new EstoqueTableModel(m.getLista());
    jTable1.setModel(model);

}
Marky.Vasconcelos

Aparece quantas linhas vazias quando abre com dois registros?

PS: Para testes, crie uma List com objetos hardcoded e crie o model para ver se essa parte funciona.

Se funcionar, o problema é na hora de trazer os dados

tperrut

Amigos,
Estou usando o meu próprio modelo “ReferenciaTableModel” extendendo de AbstractTableModel, e minha dificuldade está em tornar uma célula editavel!
Na verdade essa célula é um booleano(Logo, um CheckBox!) Não consigo editar essa célula
preciso marca-lá para que eu possa clicar em um Botão “Excluir” varrer a minhaTabela excluir todas as linhas selecionadas.

[color=red] Gostaria de saber quais métodos preciso implementar no meu modelo, ou se preciso Implementar alguma interface [/color]
segue o código…

public class ReferenciaTableModel extends AbstractTableModel {

    /**
     * long serialVersionUID
     */
    private static final long serialVersionUID = -5623699203700795223L;

    private String[] colunas = new String[] { "", "Referencia", "Descrição", "Margem Segurança" };

    /* Lista de "Alerta"(DadosTabelaReferencia) que representam as linhas. */
    private ArrayList<DadosTabelaReferencia> linhas;

    public ReferenciaTableModel() {
        this.linhas = new ArrayList();
    }

    /*
     * Cria um ReferenciaTableModel carregado com a "Alerta"(DadosTabelaReferencia) recem criado.
     */
    public ReferenciaTableModel(final ArrayList alerta, final String[] colunas) {
        this.linhas = new ArrayList<DadosTabelaReferencia>(alerta);
        this.setColunas(colunas);
    }

    /* Adiciona um registro. */
    public void addAlerta(final DadosTabelaReferencia dados) {
        // Adiciona o registro.
        this.linhas.add(dados);

        // Pega a quantidade de registros e subtrai um para achar
        // o último índice. É preciso subtrair um, pois os índices
        // começam pelo zero.
        final int ultimoIndice = this.getRowCount() - 1;

        // Reporta a mudança. O JTable recebe a notificação
        // e se redesenha permitindo que visualizemos a atualização.
        this.fireTableRowsInserted(ultimoIndice, ultimoIndice);
        return;
    }

    /**
     * @return Retorna o Objeto <code>DadosTabelaReferencia</code> da linha especificada.
     */
    public DadosTabelaReferencia getAlerta(final int indiceLinha) {
        return this.linhas.get(indiceLinha);
    }

    /**
     * Este método é usado pela JTable na hora de definir o editor da célula.
     * @return Retorna a classe dos elementos da coluna especificada.
     */
    @Override
    public Class<?> getColumnClass(final 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 campo ativo, que é um boolean.
                return Boolean.class;
            case 1: // Segunda coluna é o referencia, que é um int..
                return Integer.class;
            case 2: // Terceira coluna é a Descrição, que é uma String..
                return String.class;
            case 3: // Quarta coluna é a Margem , que também é um int..
                return Integer.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 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 this.colunas.length;
    }

    /*
     * 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(final int columnIndex) {
        // Retorna o conteúdo do Array que possui o nome das colunas
        // no índice especificado.
        return this.colunas[columnIndex];
    }

    public String[] getColunas() {
        return this.colunas;
    }

    public ArrayList getLinhas() {
        return this.linhas;
    }

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

    /**
     * @return Retorna o valor da célula especificada pelos índices da linha e da coluna.
     */
    @Override
    public Object getValueAt(final int rowIndex, final int columnIndex) {
        // Pega "o alerta" da linha especificada.
        final DadosTabelaReferencia dados = this.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ão as mesmas
        // que foram especificadas no array "colunas".

        switch (columnIndex) {
            case 0: // Primeira coluna é JCheckBox que seve pra selecionar a linha para exclusão.
                return new Boolean(false);
            case 1: // Segunda coluna é o referencia, que é um int..
                return dados.getReferencia();
            case 2: // Terceira coluna é a Descrição, que é uma String..
                return dados.getDescricao();
            case 3: // Quarta coluna é a Margem , que também é um int..
                return dados.getMargemSeguranca();
            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 final é inválido,
                // pois o próprio ArrayList lança a exceção caso seja inválido.
                throw new IndexOutOfBoundsException("columnIndex out of bounds");
        }

    }

    /**
     * Retorna um valor booleano que define se a célula em questão pode ser editada ou não. Este método é utilizado pela JTable na hora de definir o editor da célula.
     * @return <code>true</code>, apenas para a primeira coluna, não permitindo que outras células sejam editadas.
     */
    @Override
    public boolean isCellEditable(final int rowIndex, final int columnIndex) {
        // a única célula que deve ser editável é  columnIndex 0  
        return (columnIndex == 0) ? true : false;

    }

    public void setColunas(final String[] strings) {
        this.colunas = strings;
    }

    public void setLinhas(final ArrayList list) {
        this.linhas = list;
    }

    @Override
    public void setValueAt(final Object aValue, final int rowIndex, final int columnIndex) {
        // Pega "o alerta" da linha especificada.
        final DadosTabelaReferencia dados = this.linhas.get(rowIndex);

        if (columnIndex == 0) {
            dados.setAtivo((Boolean) aValue);
        }

        this.fireTableCellUpdated(rowIndex, columnIndex);

    }

Todo código desse “modelo” eu fiz estudando aqui no fórum, porém já estou há alguns dias tentando resolver e
não consegui tornar essa célula editável, Gostaria de um Help não sei mais pra onde ir!!
Grato!

Eric_Yuzo
CaioNascimento:
Então eu fiz esse metodo , quando ilinicializa aparece todos os campos com os nomes nas colunas, mas não aparece nenhum Item.
Está faltando retornar o valor do campo no método getValueAt. Da forma que está, vai sempre retornar uma String vazia:
public Object getValueAt(int linha, int coluna) {  
        
        Estoque e = (Estoque) estoque.get(linha);  
        switch (coluna){  
            case 0:  
            return e.getNome();  // retorna o valor do nome e assim por diante
            case 1:  
            return e.getObs();  
            case 2:  
            return e.getObs();  
            case 3:  
            return e.getVCompra();  
            case 4:  
            return e.getVVenda();  
            case 5:  
            return e.getLucro();  
            default:  
         return "";  
     }
Eric_Yuzo

tperrut:
Todo código desse “modelo” eu fiz estudando aqui no fórum, porém já estou há alguns dias tentando resolver e
não consegui tornar essa célula editável, Gostaria de um Help não sei mais pra onde ir!!
Grato!

O problema está no getValueAt, que sempre vai dizer pra JTable que a primeira coluna tem valor false:

switch (columnIndex) { case 0: // Primeira coluna é JCheckBox que seve pra selecionar a linha para exclusão. return new Boolean(false); // está retornando false independente do que foi setado no objeto
Este trecho deveria retornar o estado do objeto referente a coluna:

switch (columnIndex) { case 0: // Primeira coluna é JCheckBox que seve pra selecionar a linha para exclusão. return dados.isAtivo(); // retorna o estado do objeto

C

@Eric

Era isso mesmo Funcionou.

1° Só para completar me tira outra dúvida como nesse caso eu implemento um ListSelectionListener. gostaria que no evento de mudar de registro dentro da table retornace o valor para um jTextField.

Jtext.setText(jTable1.getValueAt(jTable1.getSelectedRow(),0).toString()); // E assim por diante
2° Caso eu precise listar outros dados tenho que criar uma outra classse TableModel?

Eric_Yuzo

CaioNascimento:
1° Só para completar me tira outra dúvida como nesse caso eu implemento um ListSelectionListener. gostaria que no evento de mudar de registro dentro da table retornace o valor para um jTextField.

Jtext.setText(jTable1.getValueAt(jTable1.getSelectedRow(),0).toString()); // E assim por diante


Eu diria para criar um método que retorna o objeto estoque referente a uma linha especificada no table model.

// método que retorna o objeto do table model public Estoque getData(int index) { return (Estoque) estoque.get(index); }
A partir daí pode carregar os text fields.

Estoque e = model.getData(jTable1.getSelectedRow()); txtNome.setText(e.getNome());

Basicamente sim. Ou então pode usar o ObjectTableModel do projeto Towel, feito pelo Mark. Aí não precisa escrever vários models. :slight_smile:

tperrut

Eric Yuzo:

O problema está no getValueAt, que sempre vai dizer pra JTable que a primeira coluna tem valor false:

switch (columnIndex) { case 0: // Primeira coluna é JCheckBox que seve pra selecionar a linha para exclusão. return new Boolean(false); // está retornando false independente do que foi setado no objeto
Este trecho deveria retornar o estado do objeto referente a coluna:

switch (columnIndex) { case 0: // Primeira coluna é JCheckBox que seve pra selecionar a linha para exclusão. return dados.isAtivo(); // retorna o estado do objeto

Fiz essa alteração que você observou, mas não surtiu efeito :frowning:
Reforço a pergunta:
[color=brown]Gostaria de saber quais métodos preciso implementar no meu modelo para que uma célula especifica seja editada???
ou se preciso Implementar alguma interface ou criar outra classe extendendo de CellRenderer?[/color]

Marky.Vasconcelos

É o “isCellEditable” mesmo, e pelo visto, voce já implementou.

Faça um debug, e veja se o setValueAt esta sendo chamado.

tperrut

Marky.Vasconcelos:
É o “isCellEditable” mesmo, e pelo visto, voce já implementou.

Faça um debug, e veja se o setValueAt esta sendo chamado.


Então ele não esta sendo chamado… o que poderia ser?
Outra coisa eu preciso ter uma classe
que extends AbstractCellEditor implements TableCellEditor???

Marky.Vasconcelos

CellEditor e TableModel teoricamente são coisas separadas, acho que não é legal juntar.

Marky.Vasconcelos

Só para teste, coloca um return true no isCellEditable e veja se em algum momento o setValueAt é chamado.

tperrut

Mudei para True, mas Não chama!!! ele deveria chamar o setValueAt em que momento?
no momento em que a célula esta sendo renderizada ou quando clico em alguma célula?
pois ele nunca é chamado…
[color=darkblue]vlw pela força Marky[/color]

Marky.Vasconcelos

Ele deve chamar assim que voce alterar alguma celula.

No caso de boolean que aparece um checkbox, ao clicar nele esse método é disparado.

Em texto, assim que voce termina de editar e sai da celula.

Faça esse texto nos outros campos para ver se ele é chamado.

tperrut

Fala Marky,
Pow cara não chama em momento algum!!!
Tenho outros exemplos aqui e basta retornar true no isCellEditable
e todas as colunas ficam editáveis no meu modelo ReferenciaTableModel
o setValueAt nunca é chamado…
não da certo de forma alguma o que poderia ser?

C

@Marky

è possivel o tableModel abrir com dados de 3 classes por exemplo? Codcliente e codproduto sao chaves estrangeiras de outras tabelas aparentemente era para funcionar porém está ocorrendo um erro quando tento abrir.

Tipo:

public class PedidosTableModel extends AbstractTableModel{

     private List pedidos;


    public PedidosTableModel() {
        pedidos = new ArrayList();
    }

    public PedidosTableModel(List lista) {
        this();
        pedidos.addAll(lista);
    }

    public int getRowCount() {

        return pedidos.size();
    }

    public int getColumnCount() {

        return 10;
    } Ui

    @Override
    public String getColumnName(int column) {
        //qual o nome da coluna
        switch (column){
                 case 0:
                return "Codigo";
                 case 1:
                return "Cliente";
                 case 2:
                return "Produto";
                 case 3:
                return "Qnt";
                 case 4:
                return "Valor";
                 case 5:
                return "Data";
                 case 6:
                return "Status";
                case 7:
                return "Pago";
 
            // codId é da tabelaa clientes
            case 8:
                return "codCliente";
                   
            //CodProduto é da table produto
            case 9:
                return "codProduto";

            default:
        return "";
    }
    }

    @Override
    public Class getColumnClass(int coluna) {
        //Retorna todas as colunas
        return String.class;
    }

    public Object getValueAt(int linha, int coluna) {

       Pedidos p = (Pedidos) pedidos.get(linha);
       Clientes c = (Clientes) pedidos.get(linha);
       Estoque e = (Estoque) pedidos.get(linha);

       switch (coluna){
             case 0:
          return p.getIdPedidos();
           case 1:
          return p.getCliente();
           case 2:
          return p.getProduto();
           case 3:
          return p.getQnt();
           case 4:
          return p.getValor();
           case 5:
          return p.getData();
           case 6:
          return p.getStatus();
          case 7:
          return p.getPago();
           case 8:
          return c.getIdCliente();
           case 9:
          return e.getCode();
           default:
        return "";
    }
    }
    @Override
    public void setValueAt(Object valor, int linha, int coluna) {

        Pedidos p = (Pedidos) pedidos.get(linha);
          Clientes c = (Clientes) pedidos.get(linha);
       Estoque e = (Estoque) pedidos.get(linha);

       // DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
        switch(coluna){

             case 0:
           p.setIdPedidos(Integer.parseInt(valor.toString()));
           break;

           case 1:
           p.setCliente(valor.toString());
           break;

           case 2:
           p.setProduto(valor.toString());
           break;

           case 3:
            p.setQnt(Integer.parseInt(valor.toString()));
           break;

           case 4:
            p.setStatus(valor.toString());
           break;

           case 5:
        
           p.setData((valor.toString()));
        
           break;

           case 6:
          p.setStatus(valor.toString());
           break;
             case 7:
          p.setPago(valor.toString());
           break;
                  case 8:
          c.setIdCliente(Integer.parseInt(valor.toString()));
           break;
                  case 9:
          e.setCode(Integer.parseInt(valor.toString()));
           break;


        }


        fireTableDataChanged();
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {

        return true;


}

    public Pedidos getValoresPedidos(int rowIndex){
        return (Pedidos) pedidos.get(rowIndex);
    }

}
run:
[EL Info]: 2011-06-16 15:04:08.448--ServerSession(27134372)--EclipseLink, version: Eclipse Persistence Services - 2.0.2.v20100323-r6872
[EL Info]: 2011-06-16 15:04:09.083--ServerSession(27134372)--file:/C:/Users/Caio Fernando/Documents/NetBeansProjects/Sistema/build/classes/_SistemaPU login successful
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: sistema.Objetos.Pedidos cannot be cast to sistema.Objetos.Clientes
        at sistema.TableModel.PedidosTableModel.getValueAt(PedidosTableModel.java:97)
        at javax.swing.JTable.getValueAt(JTable.java:2686)
        at javax.swing.JTable.prepareRenderer(JTable.java:5703)
        at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2072)
        at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:1974)
        at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1770)
        at javax.swing.plaf.ComponentUI.update(ComponentUI.java:143)
        at javax.swing.JComponent.paintComponent(JComponent.java:752)
        at javax.swing.JComponent.paint(JComponent.java:1029)
        at javax.swing.JComponent.paintChildren(JComponent.java:862)
        at javax.swing.JComponent.paint(JComponent.java:1038)
        at javax.swing.JViewport.paint(JViewport.java:747)
        at javax.swing.JComponent.paintChildren(JComponent.java:862)
        at javax.swing.JComponent.paint(JComponent.java:1038)
        at javax.swing.JComponent.paintChildren(JComponent.java:862)
        at javax.swing.JComponent.paint(JComponent.java:1038)
        at javax.swing.JComponent.paintChildren(JComponent.java:862)
        at javax.swing.JComponent.paint(JComponent.java:1038)
        at javax.swing.JLayeredPane.paint(JLayeredPane.java:567)
        at javax.swing.JComponent.paintChildren(JComponent.java:862)
        at javax.swing.JComponent.paint(JComponent.java:1038)
        at javax.swing.JComponent.paintChildren(JComponent.java:862)
        at javax.swing.JComponent.paint(JComponent.java:1038)
        at javax.swing.JComponent.paintChildren(JComponent.java:862)
        at javax.swing.JComponent.paint(JComponent.java:1038)
        at javax.swing.JLayeredPane.paint(JLayeredPane.java:567)
        at javax.swing.JComponent.paintToOffscreen(JComponent.java:5124)
        at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1479)
        at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1410)
        at javax.swing.RepaintManager.paint(RepaintManager.java:1224)
        at javax.swing.JComponent._paintImmediately(JComponent.java:5072)
        at javax.swing.JComponent.paintImmediately(JComponent.java:4882)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:785)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:713)
        at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:693)
        at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:125)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
        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)
CONSTRUÍDO COM SUCESSO (tempo total: 11 segundos)
tperrut

tperrut:
Fala Marky,
Pow cara não chama em momento algum!!!
Tenho outros exemplos aqui e basta retornar true no isCellEditable
e todas as colunas ficam editáveis no meu modelo ReferenciaTableModel
o setValueAt nunca é chamado…
não da certo de forma alguma o que poderia ser?

Meu Problema era que no modelo estava tudo certo, porém a
"minha tabela" (JTable) estava desabilitada…

[color=red]this.minhaTabela.setEnabled(true);[/color][color=brown] [/color]
Problema resolvido!
Obrigado pela força

C

Ah..estou usando o metodo abaixo para lista:

public void listarPedidos() throws SQLException{
        PedidosJpaController tmp = new PedidosJpaController();

    model = new PedidosTableModel(tmp.findPedidosEntities());
Na Classe JPA:
public List<Pedidos> findPedidosEntities() {
        return findPedidosEntities(true, -1, -1);
    }
Criado 7 de junho de 2011
Ultima resposta 16 de jun. de 2011
Respostas 19
Participantes 4