Abstract table model - alterar registro da tabela onde a coluna é um objeto - RESOLVIDO

4 respostas Resolvido
F

Galera quem puder me tirar essa dúvida, procurei em vários tópicos e outros locais e não encontrei a resposta. Desde já muito obrigado pela ajuda.

No projeto preciso criar uma tabela e jogar os dados de dois ou mais objetos nessa tabela, criei o método com o select (inner join nas tabelas) que preciso na classe DAO, jogo na tabela e até ai tudo bem, o resultado está ok na jtable, o problema é na hora de alterar esses registros que são outros objetos de outras classes, no meu modo de pensar toda vez que eu altero um registro não é necessário recarregar a lista toda novamente e sim apenas atualizar aquela linha na jtable e no banco, toda vez que eu atualizo da erro na jtable e no banco está ok, criei a tabela com extends da AbstractTableModel e os métodos, mas estou enrolado nisso, alguém tem uma luz?
ou o método para atualizar?

De forma mais simplificada, tenho um cadastro de clientes com os campos a serem preenchidos e o combobox de estado a ser selecionado, quando clico no botão Atualizar os campos de preenchimentos atualizam normalmente na jtable, mas quando mudo a opção do combobox da o erro de NullPointerExceptione não atualiza na jtable mas atualiza no banco.

//MÉTODO PARA ATUALIZAR UM REGISTRO DO BANCO - CLASSE DAO
    public void update(Pessoa pessoa, Uf uf) {
        try {
            String sql = "update tbl_pessoa set nome_pessoa = ?, idade_pessoa = ?, cod_uf = ? where cod_pessoa = ?";

            PreparedStatement stmt = connection.prepareStatement(sql);
            stmt.setString(1, pessoa.getNome());
            stmt.setInt(2, pessoa.getIdade());
            stmt.setObject(3, uf.getCodUf());
            stmt.setInt(4, pessoa.getCodigo());
            
            stmt.execute();
            stmt.close();

        } catch (SQLException error) {
            throw new RuntimeException(error);
        } finally {
            try {
                connection.close();
            } catch (SQLException ex) {
                Logger.getLogger(PessoaDAO.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }//FIM DO MÉTODO ATUALIZAR 


private void btnEditarActionPerformed(java.awt.event.ActionEvent evt) {                                          
        // BOTÃO EDITAR
        try {
            int linha = this.TabelaPessoa.getSelectedRow();

            Pessoa novaPessoa = new Pessoa();
            
            novaPessoa.setNome(txtNome.getText());
            novaPessoa.setIdade(Integer.parseInt(txtIdade.getText()));
            Uf uf = (Uf)Cbestado.getSelectedItem();
            novaPessoa.setCodigo(Integer.parseInt(txtCodigo.getText()));

            PessoaDAO dao = new PessoaDAO();
            dao.update(novaPessoa, uf);
            modelo.setValueAt(novaPessoa, linha);
            JOptionPane.showMessageDialog(null, "Registro alterado com sucesso!");

            //BOTÕES NOVO, SALVAR, ATUALIZAR E EXCLUIR
            btnNovo.setEnabled(true);
            btnSalvar.setEnabled(false);
            btnEditar.setEnabled(false);
            btnExcluir.setEnabled(false);

            //FECHAR CAMPOS DO FORM
            fecharCampos();

        } catch (Exception error) {
            throw new RuntimeException(error);
        }
    }                

//MÉTODO PARA ATUALIZAR A TABELA, ATRVÉS DO OBJ E SUA RESPECTIVA LINHA DA LISTA
    public void setValueAt(Pessoa aValue, int rowIndex){
        linhas.set(rowIndex, aValue);
        fireTableRowsUpdated(rowIndex, rowIndex);
        
    }

4 Respostas

4mega

Opa td bem? Preciso do código que faz com que o ComboBox interfira no jTable. Se quiser me mandar o código fico feliz em ajudar. Mandar a aplicação seria muito mais fácil para eu analisar.

F

Obrigado 4mega,

Por onde quer que eu envie a aplicação? é uma aplicação simples que faço separadamente do projeto principal, a intenção é conseguir fazer funcionar nesse pré-projeto para então eu implementar no principal.
Eu não consegui entender ainda como alterar os registros que vem de outros objetos =(.
o código da AbstractTableModel segue abaixo.

package Tabela;

import JavaBenas.Pessoa;

import JavaBenas.Uf;

import java.util.ArrayList;

import java.util.List;

import javax.swing.table.AbstractTableModel;

/**
*

  • @author Costa
    */
    //EXTENDS = HERDADNDO DA CLASSE ABSTRACT TABLEMODEL
    //HERDANDO OS MÉTODOS OBRIGATÓRIOS DA ABSTRACT TABLE MODEL -> GETROWCOUNT, GETCOLUMNCOUNT E GETVALUET.
    public class TableModelPessoa extends AbstractTableModel {

    // COMO A TABELA VAI ARMAZENAR OBJETOS PESSOAS ENTÃO TEMOS QUE CRIAR UMA LISTA DE PESSOAS
    private ArrayList linhas;

    //CRIAR UM VETOR PARA ARMAZENAR O NOME DAS COLUNAS DA TABELA, A ORDEM DOS NOMES É A ORDEM QUE VAI APARECER NA TABELA
    private String[] colunas = {“Código”, “Nome”, “Idade”, “Sigla”};

    //MÉTODO CONSTRUTOR PARA INICIAR A LISTA DE PESSOAS, LISTA VÁZIA
    
    public TableModelPessoa() {
    
    this.linhas = new ArrayList<>();
    
    }
    
    private static final int Codigo = 0;
    
    private static final int Nome = 1;
    
    private static final int Idade = 2;
    
    private static final int sigla = 3;
    
    //MÉTODO CONSTRUTOR CONTENDO A LISTA RECEBIDA POR PARÂMETRO
    
    public TableModelPessoa(List listadePessoas) {
    
    this.linhas = new ArrayList<>(listadePessoas);
    

    }

    //MÉTODO PARA ADD UM OBJETO PESSOA AO ARRAYLIST PESSOA
    
    public void addPessoa(Pessoa p) {
    
    this.linhas.add§;
    
    // Pega a quantidade de registros e subtrai 1 para
     // achar o último índice. A subtração é necessária
     // porque os índices começam em zero.
     int ultimoIndice = getRowCount() - 1;
    
     //método para atualizar o dado add na lista de pessoa
     fireTableRowsInserted(ultimoIndice, ultimoIndice);
    

    }

    //MÉTODO PARA REMOVER UMA LINHA DA LISTA PASSANDO UM INT ROWINDEX(INDICE DA LINHA)
    
    public void removerPessoa(int rowIndex) {
    
    this.linhas.remove(rowIndex);
    
    fireTableRowsDeleted(rowIndex, rowIndex);
    
    }
    
    //MÉTODO PARA RETORNAR UM OBJ SELECIONADO NA TABELA (LINHA DA TABELA)
    
    public Pessoa getPessoa(int rowIndex) {
    
    return this.linhas.get(rowIndex);
    
    }
    
    //MÉTODO PARA LIMPAR A LISTA
    
    public void clearLista() {
    
    linhas.clear();//remove todos os elementos da lista
    
    fireTableDataChanged();
    
    }
    
    //MÉTODO PARA ATUALIZAR A TABELA, ATRVÉS DO OBJ E SUA RESPECTIVA LINHA DA LISTA
    
    public void setValueAt(Pessoa aValue, int rowIndex){
    
    <a href="//linhas.set">//linhas.set</a>(rowIndex ,aValue);
    
    linhas.set(rowIndex, aValue);
    
    fireTableRowsUpdated(rowIndex, rowIndex);
    

    }

    //ADD UMA LISTA DE PESSOAS NO FINAL DA LISTA
    
    public void addListaPessoa(List pessoas) {
    
    //PEGA O TAMANHO ANTIGO DA TABELA QUE SERVIRÁ COMO INDICE PARA O PRIMEIRO DOS NOVOS REGISTROS
    
    int indice = getRowCount();
    
    //ADICIONA TODAS AS PESSOAS
    
    linhas.addAll(pessoas);
    
    //NOTOFICA AS MUDANÇAS
    
    fireTableRowsInserted(indice, indice + pessoas.size());
    
    }
    
    //MÉTODOS HERDADOS DA ABSTRACT TABLEMODEL
    
    //MÉTODO QUE RETORNA A QUANTIDADE DE OBJETOS DENTRO DA TABELA, O NÚMERO DE OBJETOS É O MESMO NÚMERO DE LINHAS DA TABELA
    
    <a class="mention" href="/u/override">@Override</a>
    
    public int getRowCount() {
    
    return this.linhas.size();//método size retorna o quantidade de elementos da lista, ou quantidade de linhas.
    
    }
    
    //MÉTODO QUE RETORNA A QUANTIDADE DE COLUNAS DA TABELA (VETOR CRIADO  EM CIMA) = 3 colunas
    
    <a class="mention" href="/u/override">@Override</a>
    
    public int getColumnCount() {
    
    return colunas.length;//length retorna o tamanho do vetor ou o números de colunas
    
    }
    
    //MÉTODO PARA RETORNAR OS NOMES DAS COLUNAS DA TABELA REFERENTE AO INDEX PASSADO POR PARÂMETRO
    
    <a class="mention" href="/u/override">@Override</a>
    
    public String getColumnName(int columnIndex) {
    
    return colunas[columnIndex];
    
    }
    
    //MÉTODO PARA RECEBER UM INDEX COMO PARÂMETRO E RETORNAR O TIPO DE CLASSE CORRESPONDENTE À COLUNA
    
    <a class="mention" href="/u/override">@Override</a>
    
    public Class<?> getColumnClass(int columnIndex) {
    
    switch (columnIndex) {
    
    case Codigo:
    
    return int.class;
    
    case Nome:
    
    return String.class;
    
    case Idade:
    
    return int.class;
    
    case sigla:
    
    return Object.class;
    
    default:
    
    //não deve ocorrer, pois existem apenas 3 colunas
    
    throw new RuntimeException(“columnIndex out of bounds”);
    
    }
    

    }

    //MÉTODO PARA DEFINIAR QUAIS CELULAS SERÃO EDITÁVEIS OU NÃO, COM O RETORNO COMO FALSE NENHUMA CELULA SERÁ EDITÁVEL
    
    <a class="mention" href="/u/override">@Override</a>
    
    public boolean isCellEditable(int rowIndex, int columnIndex) {
    
    return false;
    
    }
    

    //MÉTODO UTILIZADO PELOS OUTROS MÉTODS PARA SETAR, DELETAR OU ATUALIZAR OS REGISTROS DA TABELA.
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {

    switch (columnIndex) {
         //retorna o código da pessoa
         case 0:
             return this.linhas.get(rowIndex).getCodigo();
         //retorna o nome da pessoa // um case com um retorno para cada atributo do objeto
         case 1:
             return this.linhas.get(rowIndex).getNome();
         //retorna a idade da pessoa    
         case 2:
             return this.linhas.get(rowIndex).getIdade();
         //retorna a sigla do objeto 
         case 3:
             return this.linhas.get(rowIndex).getObjUf().getSiglaUf();
         default:
             return this.linhas.get(rowIndex);
     }
    

    }
    }

mais uma vez muito obrigado pela ajuda.

4mega
Solucao aceita

Tente este método setValue, pois o seu não é Override, e o sistema pode n reconhecer, a não ser que vc chame diretamente este método:

@Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    Pessoa pessoa = linhas.get(rowIndex);
    switch (columnIndex){
        case 0: pessoa.setCodigo(Integer.parseInt(aValue));
        case 1: pessoa.setNome(String.valueof(aValue));
        case 2: pessoa.setIdade(Integer.parseInt(aValue));
        case 3: pessoa.setSigla(aValue);
    }
    fireTableCellUpdated(rowIndex, columnIndex);
}

Se quiser passar a apk, compacte e arraste no campo de texto quando for responder no fórum, ou clique no botão Enviar e selecione o arquivo.

Uma duvida, como vc está conseguindo editar seus dados se o método isEditable está como false?

Aliais, porque a sigla da classe UF esta como Object? Sendo que o UF é um objeto? Acredito que vc prefira mudar a sigla para char[2] ou varchar[2], acredito que ESTE era o problema.

Espero ter ajudado, duvidas responda a este tópico ou skype que esta no meu perfil.

F

Problema resolvido Clemerson, obrigado.

Pra quem tiver essa mesma dúvida lá vai a explicação do modo como o Clemerson me fez entender por skype, o método setValueAt() é usado para fazer alterações diretamente na célula da tableModel, para isso é preciso implementar o método isEditable() e deixá-lo como true, para fazer alteração na tabela utilizando o botão atualizar deve usar “table.set(jTable1.getSelectRow(), pessoa); << isso altera a pessoa da linha X”, então eu arrumei meu método e ficou assim…

public void atualizarTabela(Pessoa aValue, int rowIndex){

linhas.set(rowIndex, aValue);
    fireTableRowsUpdated(rowIndex, rowIndex);
    
}

Vejam que eu troquei o nome que estava justamente como setValueAt que não era pra ser usado nesse caso e também não estava marcado como override, com isso atualizo a linha diretamente como eu queria sem precisar fazer uma nova busca no banco de dados.

no botão atualizar ficou assim na hora de atualizar a tabela…
tabela.atualizarTabela(Pessoa, linhaSelecionada); //Pessoa é o objeto e a linhaSelecionada é a linha da tabela selecionada pelo usuário.

simples, mas eu estava confundindo usando o método setValeuAt no botão atualizar quando deveria usá-lo na edição direta da célula.

Muito Obrigado 4mega, foi de grande ajuda.

Criado 2 de outubro de 2016
Ultima resposta 4 de out. de 2016
Respostas 4
Participantes 2