Atualizar JTable da janela Frame atraves de outra Janela Frame

5 respostas
Thiago_de_Paula_Bese

Pessoal, boa noite.

Estou fazendo um sistema pra facul. Estou usando o JTable para gerar a lista de dados do banco. Tenho uma janela de departamento. Nesta, existe um objeto JTable com os departamentos cadastrados. Ate ai tudo certo! Porém quando fiz outro frame(Janela Cadastra Departamento) para adicionar um novo departamento, nao tinha pensado em como atualizar o JTable de outro Frame(Janela Departamento). O que estou procurando fazer é, na hora que clicar em inserir, o JTable da janela Departamento atualizar automaticamente com o novo departamento cadastrado. Isto eu consigo fazer na mesma Janela Frame. Mas como atualizar quando o cadastro e feito em outra Janela? Pois a janela de Departamento fica aberta (Tanto por que se eu fechar a mesma e abrir denovo, os dados sao atualizados sem problemas), mas queria nao precisar fechar a mesma e abrir denovo, e sim atualizar o JTable na hora atraves de um botao de outro Frame.

Existe alguma forma de se fazer isso?
Fiz um metodo para inserir os dados no JTable(Mas usei este apenas quando estava na mesma Janela Frame! o método nao e o problema, pois roda normal)

Segue o codigo do metodo para gerar os dados no JTable:

public void getDados(JTable pTabela)
    {
        Connection con = (Connection) new GeraConexao().getConexao();
        try
        {
            PreparedStatement stmt = (PreparedStatement) con.prepareStatement("select * from departamento");
            ResultSet rs = stmt.executeQuery();
            ResultSetMetaData rsmd = (ResultSetMetaData) rs.getMetaData();

            int cols = 0;
            for(int i = 0; i < rsmd.getColumnCount(); i++)
                cols++;

            String[] nomeCampo = new String[cols];
            for (int i = 0; i < cols; i++)
                nomeCampo[i] = rsmd.getColumnName(i+1);

            int numeroLinhas = 0;
            while(rs.next())
                numeroLinhas++;

            Object[][] dados = new Object[numeroLinhas][cols];
            rs.beforeFirst();
            int k = 0;
            while(rs.next())
            {
                for (int i = 0; i < cols; i++)
                    dados[k][i] = rs.getString(i+1);
                k++;
            }
            DefaultTableModel modelo = new DefaultTableModel(dados, nomeCampo);
            pTabela.setModel(modelo);
        }
        catch(SQLException e){}
    }

Como faço para usar este método em Um Frame(mas especifico em um botão), mas para atualizar os dados de um JTable de outra Janela Frame?

Segue o codigo da insercao da outra Janela Cadastra Departamento abaixo:

private void btAdicionaActionPerformed(java.awt.event.ActionEvent evt) {
        Departamento departamento = new Departamento();
        Connection con = (Connection) new GeraConexao().getConexao();
        try
        {
            PreparedStatement stmt = (PreparedStatement) con.prepareStatement("insert into departamento(dep_nome, dep_desc) values(?, ?)");

            departamento.setNome(this.tfNome.getText());
            departamento.setDescricao(this.taDescricao.getText());

            DepartamentoDAO depDAO = new DepartamentoDAO();

            depDAO.adiciona(departamento);

            JOptionPane.showMessageDialog(null, "Departamento Adicionado com sucesso!");

           new GeraTabela().getDados(parametro JTable) // Foi aqui que percebi a surpresa, pois a JTable que eu queria nao era do mesmo Frame!
            
        }
        catch (SQLException ex) {}
    }

Se possivel, conto com o auxilio dos amigos.

Grato :wink:

5 Respostas

R

Thiago,

No frame que contém esta JTable provavelmente vc tem um botão com algo do tipo:

public void actionPerformed(ActionEvent event) {
         if(event.getSource() == btnCadastrarDepartamento){

                  CadastrarDepartamento cd = new CadastrarDepartamento();
         }

}

correto? Então, basta adicionar um InternalFrameListener ao seu InternalFrame CadastrarDepartamento, para q execute a rotina de atualização da tabela assim q for cadastrado um novo departamento e o frame CadastrarDepartamento for fechado:

adicione estas duas linhas dentro do seu if:

FrameListener l = new FrameListener(); 
cd.addInternalFrameListener(l);

seu FrameListener pode ser algo do tipo:

private class FrameListener implements InternalFrameListener{
		public void internalFrameClosed(InternalFrameEvent e){
			preencheTabela();
		}
                //override dos demais métodos
         }
ViniGodoy

Não use o DefaultTableModel

Tem uma coisa que não consigo entender. A maior parte dos posts, o usuário perde tempo montando “DAOs”, separando classes de negócio, as vezes, até aparecem uns VOs e BOs. Mas quase ninguém perde tempo para aprender corretamente a montar a View, e acaba quebrando completamente o MVC na camada de apresentação.

Aprenda a fazer seu próprio model, baseado em suas classes de negócio. E aí siga as dicas do colega acima para transmiti-lo de uma janela para outra.

ganondorfan

Sera que eu sou único que achou complicado o table model do MarkII?

Sempre se diz aqui no fórum sobre nao utilizar o default table model, porem esta me parece ser a abordagem mais simples para se utilizar de JTables.

Marky.Vasconcelos

ganondorfan:
Sera que eu sou único que achou complicado o table model do MarkII?

Sempre se diz aqui no fórum sobre nao utilizar o default table model, porem esta me parece ser a abordagem mais simples para se utilizar de JTables.

Cara, mesmo programaticamente é ruim o DefaultTableModel, ou voce acha que passar Arrays de objetos como linhas, depois fazer o getValueAt em cada campo para montar um outro objeto, e ainda não ter por exemplo o ID na tabela por que voce nao pode mostrar para o usuario, é mais fácil?

Não digo só do meu model, mas de qualquer um que siga OO.

Diferença simples entre os dois.

List<Pessoa> pessoas = myDao.getPessoas();
DefaultTableModel model1 = getDTM();
for(Pessoa p : pessoas)
  model.addRow(new Object[]{p.getNome(), p.getRG(), p.getCPF(),p.getIdade(),p.getAniversario()});

ObjectTableModel<Pessoa> model2 = getOTM();
model.addAll(pessoas);

E isso é só para inserir, e se por exemplo a classe Pessoa ter um atributo id, no caso do DTM voce não tera ele disponivel, no caso do OTM voce só precisa pegar a Pessoa da linha e fazer um getID()

Eu fico surpreso como as pessoas ainda conseguem arrumar argumentos para dizerem que não existe problema em usar o DefaultTableModel.

ViniGodoy

ganondorfan:
Sera que eu sou único que achou complicado o table model do MarkII?

Sempre se diz aqui no fórum sobre nao utilizar o default table model, porem esta me parece ser a abordagem mais simples para se utilizar de JTables.

E eu nem sequer falei no modelo do Mark.
DefaultTableModel não é nem de longe a abordagem mais simples de se lidar com JTable. Ele ainda tem diversos problemas:

  1. Força você a fazer casts:
String nome = (String) jTable.getModel().getValueAt(row, 2);

Contra:

String nome = meuTableModel.get(row).getNome();
  1. Deixa menos flexível a mudança de coluna (veja que acima, o código já deixou hardcoded que a coluna do nome é a coluna 2, enquanto no outro código, a coluna nem apareceu).

  2. Faz cópias de dados das classes de negócio para um array. Isso tem um custo de processamento e também de memória;

  3. Não guarda a relação de que objeto de negócio corresponde a uma linha. E isso é especialmente prejudicial se você não quiser exibir o ID para o usuário, por exemplo. Ou pegar o valor de uma propriedade que não está listada no model (listar todas no model também não é a solução);

Default:

String nome = (String) seuModel.get(row, 2); //Vamos torcer para o nome ser único
Usuario usuario = UsuarioDao.procurarPorNome(nome);
txtCpf.setText(usuario.getCpf()); //Coluna que não está no JTable

Contra:

Usuario usuario = seuModel.get(row); //Sem consulta ao banco, sem problema com registros duplicados.
txtCpf.setText(usuario.getCpf());
  1. Não suporta Renderers ou Editores personalizados. Você acaba tendo que fazer uma subclasse de qualquer jeito;

  2. Mistura lógica de Model e View. Não atende bem ao padrão MVC.

Se você ainda está achando o Default simples, é porque não fez seu próprio TableModel ainda. Eu admito que é mais difícil aprender a usar o AbstractTableModel do que o Default. Mas uma vez aprendido, você nunca mais vai querer recorrer ao Default novamente.

Criado 25 de setembro de 2010
Ultima resposta 27 de set. de 2010
Respostas 5
Participantes 5