Alterar e Excluir dados de JTable com AbstractModelTable no banco de dados

35 respostas
M

Olá gente!

Bem, eu já vi uns exemplos de como fazer alterações na tabela, mas ainda não consegui entender como eu consigo mudar esses dados no banco.
To tentando com uma tabela bem simples, com dois campos: o código e o nome do tipo. O código é gerado automaticamente por uma sequencia no banco de dados, então o usuário não pode alterar ele.

Eu tenho um método alterar e um excluir no meu Controller, que são assim:
public void alterar(/**int codigotipo,*/ String nometipo) throws ParseException, SQLException {
        Tipo tipo = new Tipo();
        //tipo.setCodigo(codigotipo);
        tipo.setNome(nometipo);
         new TipoDao().alterar(tipo);
    }
    
    public void excluir(String nome) throws SQLException {
       new TipoDao().excluir(nome);
    }
No meu DAO tenho as consultas:
public void alterar(Tipo tipo) throws SQLException {
        String update = "UPDATE tipomedicamento " +
                "SET nometipo = ?" +
                "WHERE nometipo = ?";
        update(update, tipo.getNome());
    }
    
    public void excluir(String nome) throws SQLException {
        String delete = "DELETE FROM tipomedicamento WHERE nometipo = ?";
        delete(delete, nome);
    }
Tenho minha TableModel, que é basicamente igual a uma que o ViniGodoy postou de exemplo aqui no GUJ, que é assim:
package tipo.model;

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

/**
 *
 * @author Munique
 */
public class TipoTableModel extends AbstractTableModel {  
    private static final int COL_CODIGO = 0;  
    private static final int COL_NOME = 1;  
  
    private List<Tipo> valores;         
  
    public TipoTableModel(List<Tipo> valores){  
          this.valores = new ArrayList<Tipo>(valores); 
    }  
  
    public int getRowCount() {    
        return valores.size();  
    }  
  
    public int getColumnCount() {   
        return 2;  
    }  
  
    public String getColumnName(int column) {  
        if (column == COL_CODIGO) return "Código";  
        if (column == COL_NOME) return "Nome do Tipo";  
        return "";
    }  
  
    public Object getValueAt(int row, int column) {  
        Tipo nome = valores.get(row);  
        if (column == COL_CODIGO) return nome.getCodigo();  
        else if (column == COL_NOME) return nome.getNome();  
        return "";
    }  
  
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {  
        Tipo tipo = valores.get(columnIndex);   
        if (columnIndex== COL_NOME) tipo.setNome(aValue.toString());  
        else if (columnIndex== COL_CODIGO) tipo.setCodigo(Integer.parseInt(aValue.toString()));  
    }  
  
    public Class<?> getColumnClass(int columnIndex) {  
        return String.class;  
    }  
      
    public boolean isCellEditable(int rowIndex, int columnIndex) {  
        return false;  
    }  
    
    public Tipo get(int row) {  
        return valores.get(row);  
    }  
    
    /**public void getLinhaTAbela(){
        getValueAt(COL_NOME, COL_NOME);
    }*/
}

E tenho uma view chamada ControleTipo, que fiz pelo editor de Swing do Netbeans, nela eu tenho botões para Inserir, Editar e Excluir. O Inserir tá funcionando certinho, mas estou tendo problemas com o editar e excluir. Alguém pode me ajudar?

35 Respostas

V

Você tem algumas opções:

  1. Passar o seu DAO para a tabela na hora de construí-la, e deixa-la chamar o método alterar no setValueAt;
  2. Implementar na sua interface gráfica um TableModelListener, e chamar lá o DAO sempre que um evento de mudança de tabela (INSERT, DELETE ou UPDATE) for disparado;
  3. Chamar o seu DAO para todas as linhas da tabela, antes de deixar a tela (só recomendo se você tiver algum tipo de controle para saber se o dado foi realmente alterado na classe de negócio, e evitar chamar desnecessariamente o banco caso contrário).
M

ViniGodoy, obrigado pelas sugestões.

Eu estou tentando implementar a partir da sua primeira sugestão, passar o meu DAO para a tabela na hora de construí-la, e deixa-la chamar o método alterar no setValueAt, mas acabei esquecendo de mencionar que o botão inserir, chama uma outra interface gráfica chamada CadastroTipo e não uma nova linha na tabela. Então, minha ideia é que a quando o usuário clicar em Alterar, essa interface CadastroTipo seja chamada também, e preenchida com os dados da linha selecionada.
Acho que não vai dar certo né?

Eu li sobre o TableModelListener, mas não entendi direito.

V

Nesse caso é muito mais fácil:

  1. Abra um JDialog modal, passe uma cópia do tipo selecionado para a JDialog;
  2. Altere esse tipo na JDialog;
  3. Se o usuário pressionar ok no seu JDialog, chame o método alterar do seu DAO sobre esse tipo, e substitua o objeto alterado pelo que está na tabela.

Há um exemplo de como trabalhar com JDialogs aqui:
http://www.guj.com.br/java/55710-jdialog-devolvendo-valor-pra-jinternalframe#292687

V

O seu método do botão ficará mais ou menos assim:

public void btnAlterarActionPerformed() {
   int index = tblTipo.getSelectedItem();
   if (index == -1)
      return;

   //Criamos o Dialog para a alteração
   TipoTableModel model = (TipoTableModel) tblTipo.getModel();

   //Estou assumindo que o construtor da JDialog faz a cópia dos valores.
   CadastroTipoDialog ctd = new CadastroTipoDialog(model.get(index)); 
   ctd.setVisible(true); //Em janelas modais, esse método trava até que ela seja fechada.

   //O método isOk não existe, vc deve cria-lo na CadastroTipoDialog.
   //Ele deve retornar true se o usuário pressionou ok, false caso contrário.
   if (!ctd.isOk()) 
      return;

   //Alteramos o tipo no banco.
   TipoDao dao = new TipoDao();
   dao.alterar(tipo);
   //Alteramos no JTable
   model.set(index, ctd.getTipo()); //getTipo deve retornar o tipo alterado
}
A implementação do método set, no seuTableModel seria assim:
public void set(int row, Tipo tip) {
    tipos.set(row, tipo);
    fireTableRowsUpdated(row, row);
}
M

Valeu Vini!

Você disse que funciona com JDialog e JFrame, certo? É que estou usando o JFrame.
Não conheço bem o JDialog, vou ler sobre ele agora, qualquer coisa posto aqui, mas muito obrigado pela ajuda até agora!

V

Não, pq o JFrame não pode ser modal.

Recomendo que faça a troca, pois dialogs modais não podem ser fechados até que o usuário conclua sua ação.
Ele bloqueia que o usuário volte a janela anterior, o que facilita muito a programação.

M

Ahhh… sério? Caracas, vou ter que fazer uns punhados de mudanças no projeto então. É que no caso esse Controle Tipo é só a classe mais ‘simples’ do sistemas, além dela tenho mais 5 telas de Cadastros e mais algumas de consultas e relatórios. Não teria como fazer uma verificação no próprio JFrame?

É que, como eu disse, não entendo muito (leia aqui:nada) do JDialog. Teriam que ser feitas muitas alterações, ou ele funciona como o JFrame?
No caso, o que seria um JDialog ‘modal’?

V

Ele é extremamente similar ao JFrame (veja o exemplo que te passei, são praticamente idênticos).

Um JDialog modal tem a propriedade modal definida para true (geralmente é só fazer seuDialog.setModal(true)). Ele não deixa o usuário acessar outras janelas até que ele seja fechado.

M

Ahá!

Consegui entender mais ou menos o funcionamento. O código do da implementação da interface gráfica pode ser o mesmo, certo? Ou ao menos eu copiei e colei ele e funcionou…
Só foi ajustar de JFrame pra JDialog… Agora vou tentar o botão!

V

Sim, pode ser o mesmo. Isso porque todos os componentes de tela (JFrame, JDialog, JInternalFrame) seguem o mesmo princípio.

Os componentes são colocados num painel central, chamado de ContentPane.
E como todo painel é um JPanel, a forma de colocar eles lá é a mesma. :slight_smile:

M
ViniGodoy:
O seu método do botão ficará mais ou menos assim:
public void btnAlterarActionPerformed() {
   int index = tblTipo.getSelectedItem();
   if (index == -1)
      return;

   //Criamos o Dialog para a alteração
   TipoTableModel model = (TipoTableModel) tblTipo.getModel();

   //Estou assumindo que o construtor da JDialog faz a cópia dos valores.
   CadastroTipoDialog ctd = new CadastroTipoDialog(model.get(index)); 
   ctd.setVisible(true); //Em janelas modais, esse método trava até que ela seja fechada.

   //O método isOk não existe, vc deve cria-lo na CadastroTipoDialog.
   //Ele deve retornar true se o usuário pressionou ok, false caso contrário.
   if (!ctd.isOk()) 
      return;

   //Alteramos o tipo no banco.
   TipoDao dao = new TipoDao();
   dao.alterar(tipo);
   //Alteramos no JTable
   model.set(index, ctd.getTipo()); //getTipo deve retornar o tipo alterado
}
A implementação do método set, no seuTableModel seria assim:
public void set(int row, Tipo tip) {
    tipos.set(row, tipo);
    fireTableRowsUpdated(row, row);
}
Vini, eu entendi o propósito, mas essa parte:
TipoDao dao = new TipoDao();  
   dao.alterar(tipo);

Isso não teria que ser chamado no Controller?

V

Sim, pode delegar diretamente para o controller.

M

Hm, acho que fiz algo errado, bem errado.

Vini, você disse que o construtor deve fazer a cópia dos valores, não é?
Não posso fazer algo como: public CadastroTipoDialog(Tipo get) { get.setNome("nometipo"); }

Acho que estou fazendo uma gambiarra total aqui, mas vai saber.

V

Se você fizer isso, o nome vai ser alterado independente do usuário pressionar no botão ok ou cancelar.
Talvez ele não seja alterado no banco, mas certamente seu JTable vai exibir o novo valor. Por isso geralmente é necessário criar uma cópia do valor.

Outra possibilidade seria carregar o tipo novamente do banco, antes de abrir o JDialog, e passar esse tipo carregado.

M

Ah sim. Não tinha nem pensando nisso.

Então vou deixar com:

CadastroTipoDialog(Tipo get) { get.getNome(); }

Eu passei isso aqui pro controller:

Tipo tipo = new Tipo(); tipo.setNome(nometipo); new TipoDao().alterar(tipo);

E no ControleTipo coloquei um ActionPerformed pro botão como você disse, tirando a parte ali de cima que coloquei no controller.
Já no CadastroTipoDialog, criei o seguinte método para getTipo:

protected Tipo getTipo() throws ParseException { TipoController tc = new TipoController(); try { tc.alterar(jTextFieldNomeTipo.getText()); JOptionPane.showMessageDialog(this, "Contato alterado com sucesso!"); } catch (SQLException e) { JOptionPane.showMessageDialog(this, "Nao foi possivel alterar contato!\n" + e.getLocalizedMessage()); } return getTipo(); }

E sei que isso tá errado, só não faço mais ideia de onde.

V

Não está faltando dizer ao seu controller quem precisa ser alterado. Como ele vai saber de que objeto aquele nome ali se refere?

M

Achei que essas linhas aqui estivesse fazendo isso:
tc.alterar(jTextFieldNomeTipo.getText());

O método alterar está no controller, então ele não vai pegar o que é pra ser alterado e o atual:

V

E como seu controller sabe qual objeto deve ser alterado?
Aí vc cria um novo controller, o que está ok.

Mas vc chama o método alterar, que deve modificar alguém já existente, entretanto, seu único parâmetro é o nome do tipo, que vem do JTextField.
Nesse caso, qual dos objetos já existentes receberá esse novo nome?

Estou questionando porque, normalmente, o método alterar recebe também o id de quem deve ser alterado. Até para ser possível montar uma query assim:

M

Ah sim… Bem, eu estava pensando em alterar só o nome mesmo e manter o mesmo ID. No caso como estou com uma sequencia, acho que ficaria:

Isso me pareceu bem estranho, mas como o usuário não pode mexer no código, acho que é a unica solução.

A minha query para Update estava assim:

V

De qualquer forma, mesmo para sua query atual, você precisaria passar o novo nome do tipo e o antigo.
O seu método alterar só está recebendo um deles.

M

É. Bem, parece meio besta, mas não daria certo se eu criasse um novo getter getNovoTipo e um setter setNovoTipo na minha classe Tipo, no model?
Ai eu poderia pegar o que já estava com o getNome e passar pelo setNovoTipo.

Edit:
Eu fiz o método para excluir e ele está excluindo, o problema é que está excluindo uma linha antes do que o usuário pede, por exemplo, se eu selecionar a linha 3 e mandar excluir-la, a linha excluída vai ser a linha 2.

V

E qual é o problema de simplesmente duplicar os dados no JDialog?
Ou de carregar seu tipo novamente do banco?

M

Bem, não há problema, eu acho, mas na honestidade, nem tenho ideia de como fazer.
Eu estou forçadamente aprendendo a lidar com Swing. Ando lendo e fuçando na API e nos fóruns mesmo, porque meu conhecimento é beeeem básico, então eu vou me baseando no que eu vejo pra ir montando a minha aplicação, mas pode deixar que vou dar mais uma olhada sobre carregar os dados.

V

Se esse é o seu caso, está indo muito bem. Os códigos que você mostrou até agora estão no caminho certo.

M

Pois é, vou indo assim. Vou tentar fazer agora, passei o dia todo mexendo com RMI pra ter um tempinho pra mexer com esse aqui agora.

Mas em relação a exclusão, alguma ideia do por que será que está excluindo errado?

M

Bem, tenho que carregar pelo construtor, certo?

Então fica ago como:

public CadastroTipoDialog(Tipo get) throws ParseException, SQLException { TipoController tc = new TipoController(); tc.alterar(get.getCodigo(), get.getNome()); }

E dai eu tenho que fazer isso de novo no getTipo?

protected Tipo getTipo() throws ParseException { TipoController tc = new TipoController(); try { tc.alterar(Integer.parseInt(jTextFieldCodigoTipo.getText()), jTextFieldNomeTipo.getText()); JOptionPane.showMessageDialog(this, "Tipo alterado com sucesso!"); } catch (SQLException e) { JOptionPane.showMessageDialog(this, "Nao foi possivel alterar tipo!\n" + e.getLocalizedMessage()); } return getTipo();

Bem, é meio obvio que não, porque não está funcionando, mas foi onde eu consegui chegar.

V

Na verdade, no construtor vc só faz a cópia do objeto para atributos do JDialog:

private boolean confirmado = false;
public CadastroTipoDialog(Tipo tipo) throws ParseException, SQLException {
     nome = tipo.getNome();        
     //Continue aqui para todos os atributos que o JDialog for mexer.     
}
Crie também um método para saber se o usuário pressionou ok ou não:
//Na ação de ok do seu JDialog, defina ok para true.
public boolean isConfirmado() {
    return confirmado;
}
E crie métodos para a leitura do que foi modificado no seu JDialog:
public String getNome() {
    return nome;
}

Na outra janela, vc poderá usar o seu Dialog assim:

public void btnAlterarClick() {
   TipoTableModel model = (TipoTableModel)suaTable.getModel();
   int index = suaTable.getSelectedIndex();
   if (index == -1) //Não selecionou nada?
      return;

   Tipo tipo = model.get(index);
   CadastroTipoDialog ctd = new CadastroTipoDialog(tipo);
   ctd.setVisible(true);
   if (!ctd.isConfirmado()) //Usuário não pressionou ok?
      return;

   //Caso seja ok, chama o controller para alterar o tipo 
   TipoController tc = new TipoController();
   tc.alterar(tipo.getCodigo(), ctd.getNome());
}

Eu sempre considero uma boa prática de programação fazer com que o JDialog não altere nada. Ele simplesmente permite que vc configure alguma coisa, e retorna o que foi configurado, mas nunca chama controllers ou métodos que efetivamente salvam objetos no banco. Isso garante que o JDialog possa ser reaproveitado em outros contextos do sistema, sem falar, que garante também que um problema de banco jamais estará num JDialog.

Claro, as vezes uma ou outra dialog mais complexa irá ferir essa regra, mas é sempre bom ter um guia de boas práticas entre os membros de sua equipe. ;)

M
Ok... Só uma coisa ficou meio confusa pra mim... No exemplo do inicio, você me falou para incluir a linha:
model.set(index, ctd.getTipo()); //getTipo deve retornar o tipo alterado

Isso atualiza minha tabela, correto?

Já estou me sentindo meio idiota, mas acho que confundiu um pouco as coisas na minha cabeça.
Vamos ver:

No controller faço o seguinte:
public void alterar(int codigotipo,
            String nometipo) throws ParseException, SQLException {
        Tipo tipo = new Tipo();
        tipo.setCodigo(codigotipo);
        tipo.setNome(nometipo);
        new TipoDao().alterar(tipo);
        
    }
No DAO Tenho o seguinte:
public void alterar(Tipo tipo) throws SQLException {
        String update = "UPDATE tipomedicamento " +
                "SET nometipo = ?" +
                "WHERE codigotipo = ?";
        update(update, tipo.getCodigo(), tipo.getNome());
    }
Vou ter mesmo que alterar o código do tipo aqui nessa query ou posso deixa-la assim? No CadastroTipoDialog tenho:
private String nome;
    private int codigo;

    public CadastroTipoDialog() {
        initComponents();
        jButtonSalvar = null;
    }
    private boolean confirmado = false;

    public CadastroTipoDialog(Tipo tipo) throws ParseException, SQLException {
        nome = tipo.getNome();
        codigo = tipo.getCodigo();
    }

    public boolean isOK() {
        if (jButtonSalvar == null) {
            jButtonSalvar = new JButton();
            jButtonSalvar.setText("Salvar");
            jButtonSalvar.addActionListener(new java.awt.event.ActionListener() {

                public void actionPerformed(java.awt.event.ActionEvent e) {
                    confirmado = true; //Dizemos que o ok foi selecionado.
                    setVisible(false);
                }
            });
        }
        return confirmado;
    }

    public boolean isConfirmado() {
        return confirmado;
    }

    public String getNome() {
        return nome;
    }

    public int getCodigo() {
        return codigo;
    }
No ControleTipo Tenho:
public void btnAlterarClick() throws ParseException, SQLException {
        TipoTableModel model = (TipoTableModel) tableTipo.getModel();
        int index = tableTipo.getSelectedRow();
        if (index == -1) //Não selecionou nada?  
        {
            return;
        }
        
        Tipo tipo = model.get(index);
        CadastroTipoDialog ctd = new CadastroTipoDialog(tipo);
        ctd.setVisible(true);
        if (!ctd.isConfirmado()) //Usuário não pressionou ok?  
        {
            return;
        }

        //Caso seja ok, chama o controller para alterar o tipo   
        TipoController tc = new TipoController();
        tc.alterar(tipo.getCodigo(), ctd.getNome());
    }
Nessa linha aqui, eu coloquei:
int index = tableTipo.getSelectedRow();
Mas no exemplo você havia posto:
int index = tableTipo.getSelectedIndex();
Esse getSelectedIndex() é uma método que eu tenho que criar? O frustrante é que parece que estou tão perto de conseguir fazer o que preciso, mas não consigo fazer algo que está na minha cara!
V

Não, o getSelectedIndex() tava errado mesmo. O nome correto do método é getSelectedRow().

Desculpe, esses probleminhas acontecem com frequencia. Você deve lembrar que eu estou dando as dicas, mas não estou na frente do seu compilador, nem com o código montado. Aí não tenho aqui o code completion. =/

Os parâmetros da sua query de alterar estão invertidos (ou parecem, não sei exatamente o comportamento do método update):

public void alterar(Tipo tipo) throws SQLException { String update = "UPDATE tipomedicamento " + "SET nometipo = ?" + "WHERE codigotipo = ?"; update(update, tipo.getNome(), tipo.getCodigo()); }

Note que aqui vc não está alterando o código. Ele é só um parametro do WHERE que indica qual dos tipos deve ser alterado.

O resto parece certo. Exceto pelo fato de eu ter esquecido um detalhe. Adicione na última linha do btnAlterarClick:

Isso avisa o Table que seu dado mudou, para que ela faça o redesenho.

E sim, você está muito perto de ver tudo funcionando. Não se frustre, são mesmo muitas peças nesse quebra-cabeças. Mas se vc apresentasse um código assim para mim numa entrevista de emprego, eu te contrataria.

M

Rapaz, nem tenho como te agradecer por toda paciência teve comigo e toda ajuda que você já meu deu aqui!

Acabei de tentar de duas maneiras: deixando o mesmo código e colocando um novo código, como fiz nos meus métodos para salvar.
Setando o código diretamente:

public void alterar(Tipo tipo) throws SQLException {
        String update = "UPDATE tipomedicamento "
                + "SET codigotipo = NEXTVAL('seq_tipomedicamento'), nometipo=? "
                + "WHERE codigotipo = ?;";
        update(update, tipo.getCodigo(), tipo.getNome());
    }
public void alterar(/**int codigotipo,*/
            String nometipo) throws ParseException, SQLException {
        Tipo tipo = new Tipo();
        //tipo.setCodigo(codigotipo);
        tipo.setNome(nometipo);
        new TipoDao().alterar(tipo);
        
    }
TipoController tc = new TipoController();
        tc.alterar(/**tipo.getCodigo(),*/ ctd.getNome());
        model.fireTableRowsUpdated(index, index);

E deixando o código:

public void alterar(Tipo tipo) throws SQLException {
        String update = "UPDATE tipomedicamento "
                + "SET codigotipo = ?, nometipo=? "
                + "WHERE codigotipo = ?;";
        update(update, tipo.getCodigo(), tipo.getNome());
    }
public void alterar(int codigotipo,
            String nometipo) throws ParseException, SQLException {
        Tipo tipo = new Tipo();
        tipo.setCodigo(codigotipo);
        tipo.setNome(nometipo);
        new TipoDao().alterar(tipo);   
    }
TipoController tc = new TipoController();
        tc.alterar(tipo.getCodigo(), ctd.getNome());
        model.fireTableRowsUpdated(index, index);

Mas nem assim aparece alguma coisa no JDialog, nem os campos sem nada... Ai fico sem ideia!

V

Mas, peraí. Seu JDialog está aparecendo vazio? Qual problema exatamente vc está tendo?

No construtor do seu JDialog vc está fazendo o setText para preencher o seu dialog?
O seu método alterar estava certo antes, como postei ali.

O erro certamente não é lá.

M

Tinha esquecido de chamar o initCompoments();... Falta de atenção ao quadrado!
Na realidade, já estava certo ontem, mas por uma falta ainda maior de atenção minha eu estava chamando o JDialog pra salvar e não alterar! Nunca ia editar mesmo!

Agora, pra excluir, eu vou ter que fazer quase a mesma coisa né? Só que não vou abrir um JDialog. Eu havia feito assim:
private void onClickExcluir() {
        TipoController tc = new TipoController();
        int index = tableTipo.getSelectedRow();
        if (index == -1) {
            return;
        }
        
        TipoTableModel model = (TipoTableModel) tableTipo.getModel();
        Tipo tipo = model.get(index);
        model.fireTableRowsDeleted(index, index);
        try {
            tc.excluir(index);
            JOptionPane.showMessageDialog(this, "Tipo excluido com sucesso!");
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(this, "Nao foi possivel excluir o tipo!\n" + e.getLocalizedMessage());
        }
    }
public void excluir(int codigoTipo) throws SQLException {
        String delete = "DELETE FROM tipomedicamento WHERE codigotipo = ?";
        delete(delete, codigoTipo);
    }
public void excluir(int codigoTipo) throws SQLException {
        new TipoDao().excluir(codigoTipo);
    }

Mas seria melhor se eu fizesse assim, não?

public ControleTipo(Tipo tipo) {
        initComponents();
        tableTipo.setModel(new TipoTableModel(new TipoController().listaTipos()));
        btnEditar = null;
        codigo = tipo.getCodigo();
    }
    
    public int getCodigo() {
        return codigo;
    }

private void onClickExcluir() {
        TipoController tc = new TipoController();
        int index = tableTipo.getSelectedRow();
        if (index == -1) {
            return;
        }
        
        TipoTableModel model = (TipoTableModel) tableTipo.getModel();
        model.fireTableRowsDeleted(index, index);
        try {
            tc.excluir(codigo);
            JOptionPane.showMessageDialog(this, "Tipo excluido com sucesso!");
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(this, "Nao foi possivel excluir o tipo!\n" + e.getLocalizedMessage());
        }
}

Achei mais coerente, mas não funciona!

V

Eu tenho uma filosofia que já me salvou muitas vezes. Quando o código está “certo demais” e não está funcionando, tente procurar o erro em outro lugar. Claro, quando vc é iniciante o código tende a parecer certo demais muito rápido, mas com o tempo, isso vira um truque valioso.

No caso, você deve efetivamente excluir o dado do seu tablemodel. Os métodos “fire” só servem para avisar a tabela que você já fez isso, mas não para realizar a ação em si.

Você precisará incluir um método no seu model para fazer a exclusão do tipo da lista que tem lá dentro:

public Tipo remove(int row) { return valores.remove(row); fireTableRowsDeleted(row, row); }

O resto parece certo. Verifique se o dado já não era excluído do banco, mas só a tela ainda estava mostrando ele lá.

M

Vini, muito obrigado! Consegui fazer tudo certinho, tive que mudar umas coisinhas, mas tá tudo funcionando certo!

Ainda tenho mais 5 cadastros bem mais difíceis que esse pra implementar, mas agora já tenho ideia de como fazer…
Sério mesmo, se não fosse você, já tinha mandando essa bagaça se explodir! Obrigado pelo tempo dedicado e pelas dicas que você me deu!

V

Opa… de nada. É como eu sempre digo. Se for para não usar o (eca) DefaultTableModel, minha paciência é de jó…

Criado 18 de junho de 2011
Ultima resposta 22 de jun. de 2011
Respostas 35
Participantes 2