Como manipular classes através de outras? [RESOLVIDO]

71 respostas
vini.roggia

Bom dia,

Estou com o seguinte problema:
Tenho uma tela principal que tem uma tabela que lista os registros. Nesta mesma tela tem um botão para adicionar um novo registro.
Acionando este botão ele abre outra tela, uma tela de cadastro no qual você preenche com os dados e aciona o botão registrar da mesma.
Feito o registro, a tela avisa que foi registrado com sucesso, dou um dispose nesta tela e retorno para a tela principal na qual tem todos os registros
listados na minha tabela. O problema é que como adicionei um novo registro ele não aparece a não ser que eu clique no botão listar registros, o qual lista novamente os registros.
O que eu gostaria é que ao cadastrar um novo registro ele chamasse o meu método da tela principal o qual lista os registros, para quando adicionado um novo e voltasse para a tela principal o novo registro estivesse la.

71 Respostas

R

Use o padrão Observer, para que uma classe possa notificar outra a respeito de quaisquer eventos de interesse.

http://en.wikipedia.org/wiki/Observer_pattern
http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/arqu/observer.htm
http://www.javaworld.com/javaworld/javaqa/2001-05/04-qa-0525-observer.html

C

Bom dia

Bom não sei se o seu problema é esse mas, pelo que vi você tem uma listagem onde tem um botão de inserir, quando vc clica no inserir chama o seu formulario, e depois que você grava as informações no banco volta para a listagem correto ? Esse formulario é aberto via poup ou na propria tela ?

Bom se for na propria tela, depois que você grava as informações no banco você tem que realizar um novo request na listagem, para que ela possa consultar o banco novamente só assim seu registro irá aparecer, da uma olhada logo após a inclusão como que esta sendo chamada a pagina de listagem.

Falou.

vini.roggia

Bom dia Caio,

Ele abre outra tela para cadastro, outra classe, outra JFrame.
Como faço para dizer na calsse telaCadastro que ao fechar ou no final do cadastro é para a classe telaPrincipal efetuar novamente a listagem?

Simattos

Bom dia

Cara nao sei se e uma boa pratica
mais resolvi esse problema com
uma simples soluçao criei um
metodo chamada Atualizar() e
quando cadastro algum item
depois que tenho a comfirmaçao
de cadastro realizado com sucesso
eu chamo o metodo Atualizar() simples
assim ok…

Abraços…

vini.roggia

Bom dia simattos,

Eu tenho esse método Atualizar(), só que ele está na classe telaPrincipal que é onde se encontra a tabela.
O problema é: Como fazer esse meu método Atualizar() executar de outra classe, no caso TelaCadastro().

Simattos
ja tentou instacia ela e chamar oi metodo.

tipo

MinhaClasse classe = new MinhaClasse();

classe.Atualizar();
Simattos

Cara vc tb pode chamar o metodo atualizar no super();
ai toda vez qua abri o programa ja atualiza automatica
no meu funcionaou…

vini.roggia

Simattos,

Então… vamos la.
Executo meu programa, abre a telaPrincipal(), nela tem o botão “Novo registro”, clico nele e abre uma NOVA tela “telaRegistro()”, ou seja, a telaPrincipal() esta ali atrás rodando normal. Se eu instânciar como dito vou estar criando uma nova telaPrincipal() “new”, o que eu quero é fazer com que seja executado o meu Atualizar() na classe que ja existe que ta ali rodando.Como se ela soubesse:

  • Olha, foi feito um novo cadastro, pode executar o Atualiza() de novo.
    Dai a telaPrincipal() executa o Atualiza().

Super()??
Não entendi isso, me explica.
Eu não vou estar criando/abrindo a telaPrincipal() novamente, ela ja vai estar ali.

acidotherwise

Ja tentou importar a classe e executar o metodo atualiza dela?

Andre_Brito

Má prática: criar uma variável static nessa telaPrincipal e, quando o botão de cadastrar for clicado, alterar essa variável pra atualizar a listagem.

Outra coisa que você pode fazer (que não sei se é a melhor “prática”), é adicionar um eventListener na tela de listagem PELA telaPrincipal. Faz um tempo que não lido com Swing, mas acho que pode funcionar.
Por exemplo:

TelaDeCadastroDeAlgumaCoisa telaDeCadastroDeAlgumaCoisa = new TelaDeCadastroDeAlgumaCoisa();
telaDeCadastroDeAlgumaCoisa.botaoDeEfeitarOCadastro.addEventListener(...);

Como eu falei, não lido com Swing a algum tempo, mas eu lembro que naquele addEventListener vai um método. E esse método seria pegar os campos cadastrados, criar um objeto e atualizar a listagem.

lina

Oi,

Você poderia criar um método Atualizar() (conforme sugerido) com padrão estático (public static void Atualizar(){}) em sua classe principal.
Quando abrir a nova tela de registro e cadastrar um novo item, chame o método estático da seguinte maneira: TelaPrinicipal.Atualizar();

Tchauzin!

vini.roggia

Boa tarde,

Lina, meu método não pode ter padrão estático pois minhas variáveis nele não são estáticos.
Tenho uma JTable dentro desse Atualiza(), com DefaultTableModel.

André, ouvi falar do eventListener, mas não sei como funciona.
Poderias me ajudar?
Onde eu colocaria esse código?

A idéia é a seguinte:
Quanto eu clico em “cadastrar” na telaCadastro(), ele registra no banco de dados, diz pro usuário que foi realizado com sucesso(JOptio…) e em seguida
ele diz para o telaPrincipal que foi adicionado um registro, ou seja, que ele tem que executar o Atualiza(); e dou um dispose() na telaCadastro(),
aparecendo a telaPrincipal() já com o novo registro.(Sendo que a tela principal sempre esteve ali, só foi atualizado a JTable com os registros dela.)

Andre_Brito

Opa, falei errado. Eu quis dizer actionListener.

Por exemplo: (os nomes estão bem “sem sentido” porque estou meio sem tempo)

// Digamos que esse arquivo seja TelaPrincipal.java

public void botaoAbrirTelaDeCadastroActionPerformed(ActionEvent evento) {
    TelaDeCadastro t = new TelaDeCadastro();
    t.setVisible();

    t.BotaoCadastrar().addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
              // Aqui vai o código para atualizar a listagem
         }
    }
}
// TelaDeCadastro.java

     // ...
     private JButton botaoDeCadastrar;

// No construtor criamos tudo e adicionamos o botão no JFrame...

     public JButton BotaoCadastrar() {
        return botaoDeCadastrar;
     }

Com isso acho que dá pra ter umas ideias de como pode ser feito.

lina

Oi,

Então... alternativas existem.

1ªopção - Janela que add novo item ser modal.

//
// Ação do botão (na tela principal) para abrir a tela de novo registro
//
new RegistroAdicionar().setVisible(true); // Irá abrir a janela e ficar travada até dar dispose.
Atualiza(); // Executa o método atualiza assim que der dispose() na janela acima.
2ªopção - Passar o botão de adicionar novo registro por parametro para ter sua referencia.
//
// Ação do botão para abrir a tela de novo registro
//
new RegistroAdicionar(<button>).setVisible(true);

//
// Ao fecha a janela..
//
dispose();
<button>.doClick();
3ªopção - Ter minhas variaveis (JTable e outras da tela principal) estaticas..

Tchauzin!

vini.roggia

Oi lina,

A 1ª opção é descartada pois tenho a idéia de ter a telaPrincipal liberada mesmo com a telaCadastro visível para uma melhor gerência dos registros.
Você poderia me explicar melhor esta 2ª opção?
Onde fica o meu método Atualiza ali?
Não entendi muito bem e me parece ser a que melhor se encaixa no que preciso.

lina

Oi,

Certo... vamos ver se conseguirei explicar melhor.

Conforme você falou, em sua tela principal, existe um botão para atualizar a tabela.
Então, esse botão você enviará como parametro ao abrir a sua nova janela (adicionar um novo registro).

//
// Exemplo resumido da tela principal.
//
public class TelaPrinicipal extends JFrame 
{
	public JButton io_atualiza;
	public JButton io_novo_registro;

	// Ação do botão novo registro (chamar o outro frame para cadastro)
	io_novo_registro.addActionListener(
		new ActionListener(){
		        public void actionPerformed(ActionEvent e){
				new TelaNovoRegistro(io_atualiza).setVisible(true);		
		        }
	      });

	// Ação do botão atualiza, chamando o método Atualizar();
	io_atualiza.addActionListener(
		new ActionListener(){
		        public void actionPerformed(ActionEvent e){
				Atualizar();	
		        }
	      });
}

Em sua tela "secundaria" de cadastro para novo registro, você criará um construtor recebendo esse botão.

public class TelaNovoRegistro extends JFrame
{
	public JButon io_atualiza;	

	// Construtor que receberá o button
	public	TelaNovoRegistro(JButton ao_button_atualiza)
	{
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

		//
		// Recebe o botão globalmente
		//
		io_atualiza	=	ao_button_atualiza;

		//
		// APOS dar operação salva com sucesso, você executa ação doClick() neste botão.
		//
		io_atualiza.doClick();

		//
		// Executa o método dispose();
		//
		dispose();
	}
}

Acho que isso resolveria seu problema.

Tchauzin!

Adaylon

Parece que no seu caso a melhor opção seja mesmo instanciar sua classe chamando o método atualizar e usar
botão.doClick();
pois isso vai disparar o evento do seu botão de atualizar.

Andre_Brito

O que eu escrevi não adianta?
Quando usava Swing, sempre usei e nunca tive problemas. No Flex idem.

Marky.Vasconcelos

Ou então leia sobre o padrão Observer. Depois de fechar a janela voce pode lançar um evento para um Listener e saber o que aconteceu com ela.

vini.roggia

Andre,

Eu não consegui implementar da forma que você colocou.
Me perdi em algum lugar.

Andre_Brito

A primeira vista pode parecer complicado, mas é bem simples. Você pode colocar o código onde você cria a tela de cadastro (que eu suponho que é dentro da classe da tela principal)?

vini.roggia

Andre,

Esse é o evento de mouse pressionado do botão “btNovo” na telaPrincipal() onde crio minha telaCadastro();

private void btNovoMousePressed(java.awt.event.MouseEvent evt) {                                    
// TODO add your handling code here:

    TelaCadastro tc = new TelaCadastro();
    tc.setVisible(true);
   
}

E esse é o evendo de mouse pressionado do botão “btCadastrar” na telaCadastro()

private void btCadastrarMousePressed(java.awt.event.MouseEvent evt) {                                         
// TODO add your handling code here:
    if(this.taDescricao.getText().isEmpty() || this.tfNomeSolicitante.getText().isEmpty()){
        JOptionPane.showMessageDialog(null, "É obrigatório o preenchimento\nde todos os campos.");
    }
    else{
    FabricaAtendimentoDAO f = new FabricaAtendimentoDAO();
    IAtendimentoDAO a = f.getAtendimentoDAO();
            setAtendimento(new AtendimentoBean());
            getAtendimento().setSolicitante(this.tfNomeSolicitante.getText());
            getAtendimento().setDepartamento(this.cbDepartamento.getSelectedItem().toString());
            getAtendimento().setDataSolicitacao(this.jtfDataSolicitacao.getText());
            getAtendimento().setCaracteristica(this.cbCaracteristica.getSelectedItem().toString());
            getAtendimento().setSolicitacao(this.taDescricao.getText());

            a.insereNoBanco(getAtendimento());

            this.cbCaracteristica.setSelectedItem(0);
            this.taDescricao.setText("");
            
            this.dispose();
            
            JOptionPane.showMessageDialog(null, "Registro inserido", "Cadastro", 1);

        }
}

Esse é o meu Atualiza() que se encontra na telaPrincipal():

public void jogaNaTabelaAberto(){
        DefaultTableModel dtm = (DefaultTableModel) this.tbAtendimento.getModel();
        dtm.setRowCount(0);
        FabricaAtendimentoDAO fab = new FabricaAtendimentoDAO();
        IAtendimentoDAO at = fab.getAtendimentoDAO();
        ArrayList<AtendimentoBean> atendimentos = at.listaCadastroChamadoAberto();
        for(int i=0;i<atendimentos.size();i++){

            dtm.setRowCount(dtm.getRowCount()+1);

                    dtm.setValueAt(atendimentos.get(i).getChamado(), dtm.getRowCount()-1,0);
                    dtm.setValueAt(atendimentos.get(i).getSolicitante(), dtm.getRowCount()-1,1);
                    dtm.setValueAt(atendimentos.get(i).getDepartamento(), dtm.getRowCount()-1,2);
                    dtm.setValueAt(atendimentos.get(i).getDataSolicitacao(), dtm.getRowCount()-1,3);
                    dtm.setValueAt(atendimentos.get(i).getSolicitacao(), dtm.getRowCount()-1,4);
                    dtm.setValueAt(atendimentos.get(i).getCaracteristica(), dtm.getRowCount()-1,5);
                    dtm.setValueAt(atendimentos.get(i).getDataAtendimento(), dtm.getRowCount()-1,6);
                    dtm.setValueAt(atendimentos.get(i).getSolucao(), dtm.getRowCount()-1,7);
                    dtm.setValueAt(atendimentos.get(i).getAtendente(), dtm.getRowCount()-1,8);
        }
    }

O que eu deveria alterar e o que eu deveria Adicionar ao meu código?

Andre_Brito

Sabe esse btCadastrarMousePressed? Então, acho que ele deve ficar na classe da tela principal.
Vai acontecer o seguinte: você tem essa classe da tela principal e a tela de cadastro. Você vai colocar um evento no botão da tela de cadastro (esse cadastrar), certo? Só que você tá colocando esse evento (ou seja, escrevendo o código do que vai acontecer), dentro da classe da tela de cadastro. Faça isso dentro da classe da tela principal. Dessa forma, você só vai poder atualizar diretamente nesse método.

Estou colocando em anexo um exemplo bem básico. Veja que eu adiciono o evento e digo o que vai acontecer se o botão for pressionado em uma classe e coloco esse botão em outra classe.

lina

Oi,

Existe algum botão na tela principal que chama este o método jogaNaTabelaAberto() ?

Tchauzin!

vini.roggia

Tem sim:

private void btListarAbertoMousePressed(java.awt.event.MouseEvent evt) {                                            
// TODO add your handling code here:
    this.jogaNaTabelaAberto();
    spAtendimento.getVerticalScrollBar().setValue(tbAtendimento.getHeight());
       
}
lina

Oi,

tudo bem… em qual local você cria o botão e quando você tem a instancia dele?

assim.: button_aberto = new JButton();

Tchauzin!

vini.roggia

Uso a IDE NetBeans 6.5
Ele cria para mim o botão.

// Variables declaration - do not modify private javax.swing.JButton btEntrar; private javax.swing.JButton btListarAberto; ...

private void initComponents() { btListarAberto = new javax.swing.JButton(); btListarAberto.setText("Listar chamados em aberto"); btListarAberto.addMouseListener(new java.awt.event.MouseAdapter() { public void mousePressed(java.awt.event.MouseEvent evt) { btListarAbertoMousePressed(evt); } }); }

Sendo que estes estão como “bloqueado” pois são criados pela IDE.

Andre_Brito

Bloqueado você quer dizer private?

É só fazer um método pra acessar o botão. Cara, vê o código que eu coloquei. Seu problema tá resolvido lá.

vini.roggia

André,

Bloqueado, quero dizer que não posso editar na IDE.
Você usa o NetBeans? Se usa, estou falando por exemplo do initComponents() que não da de editar pois a IDE que criou.
Vou dar uma estudada no seu código e ver se consigo adaptar ao meu.

Obrigado

lina

Oi,

Por isso que não utilizo visual grafico! rsrs

Na ação do btNovoMousePressed você irá chamar a tela cadastro da seguinte maneira.

private void btNovoMousePressed(java.awt.event.MouseEvent evt) {                                       
// TODO add your handling code here:   
  
    TelaCadastro tc = new TelaCadastro(btListarAberto);   
    tc.setVisible(true);   
     
}

Na sua classe TelaCadastro() você irá criar outro construtor ou então adicionar no seu construtor em sua assinatura 1 botão.:

public class TelaCadastro extends JFrame.... {

     // Criando o construtor.
     public         TelaCadastro(JButton bt_listar_aberto) {

     }
}

Logo após isso, vamos criar uma variavel JButton "GLOBAL" dentro da classe TelaCadastro() que irá receber o botão passado por parametro, ficando.:

public class TelaCadastro extends JFrame.... {

     // Criando a variavel global.
     public JButton io_bt_listar_aberto;

     // Criando o construtor.
     public         TelaCadastro(JButton bt_listar_aberto) {
                io_bt_listar_aberto = bt_listar_aberto; //Recebe o botão parametrizado
     }
}

Agora, antes de você exeuctar o método dispose() da classe TelaCadastro(), você irá dar um doClick() nesse botão global. (Isso irá fazer executar o método jogaNaTabelaAberto() da classe Principal.

io_bt_lista_aberto.doClick();
dispose();

Verifica se isso é possível!

Tchauzin!

vini.roggia

Oi Lina,

Em qual parte ali diz que o io_bt_lista_aberto.doClick(); vai acionar o método jogaNaTabelaAberto() ?

vini.roggia

Entendi já… x)
Vou testar.

vini.roggia

Não deu..
Ao clicar no botão na telaPrincipal() para abrir a telaCadastro() da o seguinte erro:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at helpdesk.visao.TelaCadastro.(TelaCadastro.java:248)
at helpdesk.visao.TelaPrincipal.btNovoMousePressed(TelaPrincipal.java:393)

sendo que na linha 393 o que tem é:
TelaCadastro tc = new TelaCadastro(btListarAberto);

O meu código ficou na telaPrincipal()

private void btNovoMousePressed(java.awt.event.MouseEvent evt) {                                    

    TelaCadastro tc = new TelaCadastro(btListarAberto);
    tc.setVisible(true);
   
}
na telaCadastro()
private void btCadastrarMousePressed(java.awt.event.MouseEvent evt) {                                         
// TODO add your handling code here:
    if(this.taDescricao.getText().isEmpty() || this.tfNomeSolicitante.getText().isEmpty()){
        JOptionPane.showMessageDialog(null, "É obrigatório o preenchimento\nde todos os campos.");
    }
    else{
    FabricaAtendimentoDAO f = new FabricaAtendimentoDAO();
    IAtendimentoDAO a = f.getAtendimentoDAO();
            setAtendimento(new AtendimentoBean());
            getAtendimento().setSolicitante(this.tfNomeSolicitante.getText());
            getAtendimento().setDepartamento(this.cbDepartamento.getSelectedItem().toString());
            getAtendimento().setDataSolicitacao(this.jtfDataSolicitacao.getText());
            getAtendimento().setCaracteristica(this.cbCaracteristica.getSelectedItem().toString());
            getAtendimento().setSolicitacao(this.taDescricao.getText());

            a.insereNoBanco(getAtendimento());

            this.cbCaracteristica.setSelectedItem(0);
            this.taDescricao.setText("");
            
            JOptionPane.showMessageDialog(null, "Registro inserido", "Cadastro", 1);

        }
}                                        

// Criando a variavel global.
     public JButton btListarAberto;

public TelaCadastro(JButton bt_listar_aberto) {
     btCadastrar.doClick();
     btListarAberto = bt_listar_aberto; //Recebe o botão parametrizado 
     btListarAberto.doClick();
     dispose();
     }

Alguma idéia?

lina

Será que quem está nullo é o btListarAberto ?
ele não foi criado ainda?

Coloque esse código no lugar, que vai indicar se o btListarAberto está nulo.

private void btNovoMousePressed(java.awt.event.MouseEvent evt) {                                         
// TODO add your handling code here:     
    System.out.println(btListarAberto == null);     
    TelaCadastro tc = new TelaCadastro(btListarAberto);     
    tc.setVisible(true);     
       
}

Se ele retornar true, você deverá cria-lo. Se for possivel modificar essa parte do código.:

// Variables declaration - do not modify                       
    private javax.swing.JButton btEntrar;   
    private javax.swing.JButton btListarAberto; ...
Mude para.:
// Variables declaration - do not modify                       
    private javax.swing.JButton btEntrar;   
    private javax.swing.JButton btListarAberto = new JButton(); ...
E teste novamente.
vini.roggia

Deu FALSE ;X

Marky.Vasconcelos

O que tem na linha

TelaCadastro.java:248

?

lina

Oi,

já sei!
o problema está neste código.:

public TelaCadastro(JButton bt_listar_aberto) { btCadastrar.doClick(); btListarAberto = bt_listar_aberto; //Recebe o botão parametrizado btListarAberto.doClick(); dispose(); }

mude para.:

public TelaCadastro(JButton bt_listar_aberto) { btListarAberto = bt_listar_aberto; //Recebe o botão parametrizado btListarAberto.doClick(); dispose(); }

lina

Mark_Ameba:
O que tem na linha

TelaCadastro.java:248

?

Oi,

Eu iria fazer essa pergunta…

ficou uma carinha no lugar do 8… e não tinha a certeza que era linha 248… rs

Tchauzin!

vini.roggia

Ta assim, mas continua o erro.

int pressionado=0;
    TelaCadastro(JButton btListarAberto) {
        initComponents();

        this.setLocationRelativeTo(null);
        this.setIconImage(Toolkit.getDefaultToolkit().getImage(TelaMenu.class.getResource("/helpdesk/icon.jpg")));
        DefaultComboBoxModel dcbm=(DefaultComboBoxModel) this.cbDepartamento.getModel();

        System.out.println(btListarAberto == null);//esta dando false
        btListarAberto = bt_listar_aberto; //Recebe o botão parametrizado
        btListarAberto.doClick();
        if(pressionado==1)//pressionado recebe 1 quando clicado no botão Cadastrar
        dispose();
    }


 public JButton btListarAberto;

private void btCadastrarMousePressed(java.awt.event.MouseEvent evt) {                                         
// TODO add your handling code here:
    if(this.taDescricao.getText().isEmpty() || this.tfNomeSolicitante.getText().isEmpty()){
        JOptionPane.showMessageDialog(null, "É obrigatório o preenchimento\nde todos os campos.");
    }
    else{
    FabricaAtendimentoDAO f = new FabricaAtendimentoDAO();
    IAtendimentoDAO a = f.getAtendimentoDAO();
            setAtendimento(new AtendimentoBean());
            getAtendimento().setSolicitante(this.tfNomeSolicitante.getText());
            getAtendimento().setDepartamento(this.cbDepartamento.getSelectedItem().toString());
            getAtendimento().setDataSolicitacao(this.jtfDataSolicitacao.getText());
            getAtendimento().setCaracteristica(this.cbCaracteristica.getSelectedItem().toString());
            getAtendimento().setSolicitacao(this.taDescricao.getText());

            a.insereNoBanco(getAtendimento());

            this.cbCaracteristica.setSelectedItem(0);
            this.taDescricao.setText("");
            
            //this.dispose();
            
            JOptionPane.showMessageDialog(null, "Registro inserido", "Cadastro", 1);
            pressionado=1;
        }
}

aH, a linha 248 se não me engano era do iniComponents()
agora o erro que da é o seguinte:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at helpdesk.visao.TelaCadastro.(TelaCadastro.java:46)
at helpdesk.visao.TelaMenu.btNovoMousePressed(TelaMenu.java:392)

linha 46 btListarAberto.doClick();
linha 392 TelaCadastro tc = new TelaCadastro(btListarAberto);

lina

Oi,

então… a variavel nulla é btListarAberto.

Você está recebendo o botão que foi passado pelo parâmetro e jogando nesta variavel? não tem como passar essas classes inteiras para dar uma olhada?

Tchauzin!

Marky.Vasconcelos
TelaCadastro(JButton btListarAberto) {
        btListarAberto = bt_listar_aberto; //Recebe o botão parametrizado
        btListarAberto.doClick();
    }

Voce esta recebendo o parametro btListarAberto e atribui a ela o valor de bt_listar_aberto que esta null.

Para funcionar.

TelaCadastro(JButton btListarAberto) {
        initComponents();

        this.setLocationRelativeTo(null);
        this.setIconImage(Toolkit.getDefaultToolkit().getImage(TelaMenu.class.getResource("/helpdesk/icon.jpg")));
        DefaultComboBoxModel dcbm=(DefaultComboBoxModel) this.cbDepartamento.getModel();

        System.out.println(btListarAberto == null);//esta dando false
        this.bt_listar_aberto = btListarAberto;
        bt_listar_aberto.doClick();
        if(pressionado==1)//pressionado recebe 1 quando clicado no botão Cadastrar
        dispose();
    }
vini.roggia

Rodou sem erro Mark, mas não atualizou a JTable.
O que pode ser?

Marky.Vasconcelos

Por que o evento é chamado antes de pressionada o botão cadastrar. Voce deve chamar o bt_listar_aberto.doClick() dentro da ação do botão cadastrar.

Poste a ação dele para vermos.

vini.roggia

Bom dia Marck,

Segue o código atual:

TelaMenu()
private void btNovoMousePressed(java.awt.event.MouseEvent evt) {                                    
// TODO add your handling code here:
    TelaCadastro tc = new TelaCadastro(btListarAberto);//(btListarAberto)
    tc.setVisible(true);

}
TelaCadastro()
private AtendimentoBean atendimento;
    private JButton bt_listar_aberto;
TelaCadastro(JButton btListarAberto) {
        initComponents();

        this.setLocationRelativeTo(null);
        this.setIconImage(Toolkit.getDefaultToolkit().getImage(TelaMenu.class.getResource("/helpdesk/icon.jpg")));
        DefaultComboBoxModel dcbm=(DefaultComboBoxModel) this.cbDepartamento.getModel();

    }

private void btCadastrarMousePressed(java.awt.event.MouseEvent evt) {                                         
// TODO add your handling code here:
    if(this.taDescricao.getText().isEmpty() || this.tfNomeSolicitante.getText().isEmpty()){
        JOptionPane.showMessageDialog(null, "É obrigatório o preenchimento\nde todos os campos.");
    }
    else{
    FabricaAtendimentoDAO f = new FabricaAtendimentoDAO();
    IAtendimentoDAO a = f.getAtendimentoDAO();
            setAtendimento(new AtendimentoBean());
            getAtendimento().setSolicitante(this.tfNomeSolicitante.getText());
            getAtendimento().setDepartamento(this.cbDepartamento.getSelectedItem().toString());
            getAtendimento().setDataSolicitacao(this.jtfDataSolicitacao.getText());
            getAtendimento().setCaracteristica(this.cbCaracteristica.getSelectedItem().toString());
            getAtendimento().setSolicitacao(this.taDescricao.getText());

            a.insereNoBanco(getAtendimento());

            this.cbCaracteristica.setSelectedItem(0);
            this.taDescricao.setText("");
            
            JOptionPane.showMessageDialog(null, "Registro inserido", "Cadastro", 1);

            System.out.println(btListarAberto == null);//esta dando TRUE
            this.bt_listar_aberto=btListarAberto; //Recebe o botão parametrizado
            System.out.println("Fazer listagem");
            this.bt_listar_aberto.doClick();

            this.dispose();

        }
}

O erro que está dando agora é ao clicar em Cadastrar:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at helpdesk.visao.TelaCadastro.btCadastrarMousePressed(TelaCadastro.java:255)

linha 255: this.bt_listar_aberto.doClick();

Alguma idéia?

D

Ola!
Acho que a mlehor forma de vc fazer isso é através do padrão Observer…
Assim quando vc fizer seu cadastro, vc envia uma notificação para sua janela principal para que ela atualize a tabela.

Eu utilizo bastante este padrão em diversas situações, creio que seja a melhor forma para isso.

Da uma pesquisada a respeito, caso não entenda posso tentar ajudar.

vini.roggia

Bom dia Danilo,

Ouvi falar sobre este padrão Observer, mas não sei implementar.
Agradeceria muito se você pudesse me ajudar, até mesmo com exemplos de como aplicar para eu aprender.

vini.roggia

Bom dia Danilo,

Ouvi falar sobre este padrão Observer, mas não sei implementar.
Agradeceria muito se você pudesse me ajudar, até mesmo com exemplos de como aplicar para eu aprender.

lina

Oi,

na TelaCadastro() você tem que fazer isso.:

private AtendimentoBean atendimento;
    private JButton bt_listar_aberto;
TelaCadastro(JButton btListarAberto) {
        initComponents();
           
        System.out.println(btListarAberto == null);
        this.bt_listar_aberto = btListarAberto; // Essa linha é necessária dentro do construtor.

        this.setLocationRelativeTo(null);
        this.setIconImage(Toolkit.getDefaultToolkit().getImage(TelaMenu.class.getResource("/helpdesk/icon.jpg")));
        DefaultComboBoxModel dcbm=(DefaultComboBoxModel) this.cbDepartamento.getModel();

    }

private void btCadastrarMousePressed(java.awt.event.MouseEvent evt) {                                         
// TODO add your handling code here:
    if(this.taDescricao.getText().isEmpty() || this.tfNomeSolicitante.getText().isEmpty()){
        JOptionPane.showMessageDialog(null, "É obrigatório o preenchimento\nde todos os campos.");
    }
    else{
    FabricaAtendimentoDAO f = new FabricaAtendimentoDAO();
    IAtendimentoDAO a = f.getAtendimentoDAO();
            setAtendimento(new AtendimentoBean());
            getAtendimento().setSolicitante(this.tfNomeSolicitante.getText());
            getAtendimento().setDepartamento(this.cbDepartamento.getSelectedItem().toString());
            getAtendimento().setDataSolicitacao(this.jtfDataSolicitacao.getText());
            getAtendimento().setCaracteristica(this.cbCaracteristica.getSelectedItem().toString());
            getAtendimento().setSolicitacao(this.taDescricao.getText());

            a.insereNoBanco(getAtendimento());

            this.cbCaracteristica.setSelectedItem(0);
            this.taDescricao.setText("");
            
            JOptionPane.showMessageDialog(null, "Registro inserido", "Cadastro", 1);

            // Pode retirar essas 2 linhas abaixo.

            //System.out.println(btListarAberto == null);//esta dando TRUE
            //this.bt_listar_aberto=btListarAberto; //Recebe o botão parametrizado

            System.out.println("Fazer listagem");
            this.bt_listar_aberto.doClick();

            this.dispose();

        }
}

Ok?

Tchauzin!

vini.roggia

Bom dia Lina,

Fiz exatamente como você me falou e ele não da nenhum erro de compilação, MASS… a JTable não é atualizada.
Alguma idéia?

lina

Oi,

Bom dia… Coloque um sysout dentro do método que Atualiza a JTable e vamos ver se ao menos ele está entrando!

Tchauzin!

Marky.Vasconcelos

Cade a action do botao que lista?

lina

Oi,

Fiz uma simulação para provar que funciona...

TelaPrincipal():

public class TelaPrincipal extends JFrame
{
	public JButton io_atualiza;
	public JButton io_novo_registro;
	
	public TelaPrincipal()
	{
		setSize(500,500);
		setLayout(null);
		io_atualiza		=	new JButton();
		io_atualiza.setBounds(10,10,100,20);
		io_atualiza.setText("Atualizar");
		io_atualiza.addActionListener(
				new ActionListener(){
				        public void actionPerformed(ActionEvent e){
				        	System.out.println("Entrou!!!");
				        }
			      });
		getContentPane().add(io_atualiza);
		
		// Ação do botão novo registro (chamar o outro frame para cadastro)
		io_novo_registro	=	new JButton();
		io_novo_registro.setBounds(10,100,100,20);
		io_novo_registro.setText("Novo registro");
		io_novo_registro.addActionListener(
			new ActionListener(){
			        public void actionPerformed(ActionEvent e){			        	
					new TelaNovoRegistro(io_atualiza).setVisible(true);		
			        }
		      });
		getContentPane().add(io_novo_registro);
	}
	
	public static void main(String args[])
	{
		new TelaPrincipal().setVisible(true);
	}
}

TelaNovoRegistro():

public class TelaNovoRegistro	extends	JFrame
{
	public JButton	io_button;
	
	public		TelaNovoRegistro(JButton ao_button)
	{
		setLayout(null);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		this.io_button		=	ao_button;
		
		this.io_button.doClick();
		
		dispose();
	}
}

Quando clicado no botão Novo Registro da TelaPrincipal, ele irá executar o doClick() e sai no sysout = Entrou!!!

Tchauzin!

vini.roggia

Lina,

No meu ele entra a primeira vez(Quando abre a telaPrincipal() e dai ele lista os registros em aberto) mas dai então eu abro a tela de novo registro, preencho os campos e quando clico no botão registrar ele não entra novamente.
Quando eu clicasse em Registrar ele devia enviar o registro ao banco de dados, dar o aviso de registro incluido, LISTAR NOVAMENTE A JTABLE da outra classe e ai sim dar um dispose. Só que ele passa pela linha this.bt_listar_aberto.doClick(); e nada acontece e dai ele fecha a tela.

D

No padrão Obsever você possui dois tipos de classes, as classes que desejam receber uma notificação e as classes que enviam uma notificação.
Vou te explicar o modo que utilizo o padrão, mas é bom vc entender ele.
Para maiores detalhes vc pode pesquisar aqui http://www.guj.com.br/article.show.logic?id=47 ou google tb te trará vários resultados.

Eu costumo fazer uma adaptação deste padrão, o motivo vc poderá entender aqui http://www.guj.com.br/posts/list/117731.java

Segue abaixo o modo como faço ...
Eu crio duas interfaces: Observer e Subject

public interface Observer {
	/**
	 * Recebe a notificação da classe que está sendo observada.	 
	 * @param Object[] - notificação(s) enviada da classe observada.	 
	 * */
	public void update(Object[] arg );	
}
public interface Subject {
	
       /**Adiciona as classes que devem ser notificadas.*/
       public void addObserver(Observer o);
	/**Remove uma determinada classe da lista de classes que devem ser notificadas.*/
       public void removeObserver(Observer o);
     /**
      * Notifica as classes observadoras de um determinado evento.
      * */
     public void notifyObservers();
    
}

A(s) classe(s) que deseja(m) receber uma notificação, deverá(o) implementar a interface Observer.
A(s) classe(s) que irá(o) enviar uma notificação, deverá(o) implementar a interface Subject.

No seu caso, a sua tela principal que contém a tabela para listar os registros é a classe que deseja ser notificada, então ela implementa a interface Observer.
A sua tela de cadastro deverá implementar a interface Subject.

Bom.. la na sua tela de cadastro, a qual implementa a Subject, vc deve criar um ArrayList que conterá todas as classes que desejam ser notificadas:
public class ClasseQueNotifica  implements Subject(){
   private ArrayList<Observer> observers = new ArrayList<Observer>();
   ...
}
Vc ja deve saber que quando implementa uma interface vc deve implementar os métodos dela, certo? Os métodos addObserver e removeObserver ficarão assim :
public void addObserver(Observer o) {
       observers.add(o);
}

public void removeObserver(Observer o) {
      observers.remove(o);
}
Lá na sua classe principal (Observadora), em algum momento (após instanciar sua classe a qual implementa Subject), você deve chamar o método addObserver passando a classe principal como parâmetro, por exemplo:
public class ClasseQueRecebeNotificacao() implements Observer(){
   ...
   private void adicionarObserver(){
        instanciaDaClasseQueNotifica.addObserver(this);
   }
 ...
}
Sua classe que implementa Subject, sempre que desejar enviar uma notificação, deverá chamar o método notifyObservers. O método deverá ser implementado semelhante ao abaixo:
public void notifyObservers() {	   
		
	   Iterator i = observers.iterator();
	   while( i.hasNext() ) {
		   Observer o = (Observer) i.next();
		   o.update(new Boolean[]{true});
	   }
}
No caso acima, sempre que for chamado este método, ele enviará um boolean - true para a(s) classe(s) que está(o) esperando por uma notificação, porém vc pode fazer como quiser, mandar o que quiser, vc é quem faz sua lógica. Então, após cadastrar os dados no banco e certificar que foi sucesso, vc chama o método notifyObservers. É importante saber que a classe a qual receberá a notificação, deve conhecer o que poderá chegar para ela(nesse caso um boolean). Este método irá chamar o método update da classe principal correto? Lá no método update vc verifica se está recebendo um boolean - true , por exemplo, se sim vc recarrega a tabela. (No caso deste exemplo que passei sempre será true) . Um exemplo do método update:
public void update(Object[] arg) {
     /*Neste caso, a classe já sabe que chegará apenas um objeto como notificação*/
		if(arg[0] instanceof Boolean){
                          /*Se for true*/
			if(((Boolean)arg[0]).booleanValue()){
                           preencherTabela();
                       }
		}

	}
Como já disse, a lógica vc quem faz, se puder receber mais de um objeto, ou diferentes tipos de objetos, é vc quem trata como irá controlar isso. A princípio pode parecer um pouco confuso, mas é bem simples na verdade, e muito útil. Eu utilizo muito esse padrão. Porém é legal vc dar uma olhada nos links que te passei ou pesquisar um pouco mais para entender melhor tudo o que te passei aqui.
Marky.Vasconcelos

Os listeners do swing é uma implementação do padrão Observer.

Realmente é a melhor maneira.

lina

Oi,

Sim! O padrão Observer é melhor, só não entendo o pq o código doClick não funciona.

Fiz o teste e funcionou corretamente… só pode ser esses métodos criados e fixados pelo próprio netbeans…

Desculpe não poder ajudar, já não sei + o que fazer =/

Tchauzin!

Marky.Vasconcelos
private AtendimentoBean atendimento;
    private JButton bt_listar_aberto;
TelaCadastro(JButton btListarAberto) {
        initComponents();

        this.setLocationRelativeTo(null);
        this.setIconImage(Toolkit.getDefaultToolkit().getImage(TelaMenu.class.getResource("/helpdesk/icon.jpg")));
        bt_listar_aberto = btListarAberto;

    }

private void btCadastrarMousePressed(java.awt.event.MouseEvent evt) {                                         
// TODO add your handling code here:
    if(this.taDescricao.getText().isEmpty() || this.tfNomeSolicitante.getText().isEmpty()){
        JOptionPane.showMessageDialog(null, "É obrigatório o preenchimento\nde todos os campos.");
    }
    else{
    FabricaAtendimentoDAO f = new FabricaAtendimentoDAO();
    IAtendimentoDAO a = f.getAtendimentoDAO();
            setAtendimento(new AtendimentoBean());
            getAtendimento().setSolicitante(this.tfNomeSolicitante.getText());
            getAtendimento().setDepartamento(this.cbDepartamento.getSelectedItem().toString());
            getAtendimento().setDataSolicitacao(this.jtfDataSolicitacao.getText());
            getAtendimento().setCaracteristica(this.cbCaracteristica.getSelectedItem().toString());
            getAtendimento().setSolicitacao(this.taDescricao.getText());

            a.insereNoBanco(getAtendimento());

            this.cbCaracteristica.setSelectedItem(0);
            this.taDescricao.setText("");
            
            JOptionPane.showMessageDialog(null, "Registro inserido", "Cadastro", 1);

           this.bt_listar_aberto.doClick();

            this.dispose();

        }
}
vini.roggia

Meu código está exatamente como o Marck colocou.
Não entendo porque não funciona, na teoria está tudo certo.
Vou estudar sobre Observer e Subject, caso eu tenha algum outro resultado posto aqui.
Caso alguém encontre a solução, sinta-se a vontade para compartilhar.

Marky.Vasconcelos

Posta o código de insereNoBanco da classe IAtendimentoDAO e o ActionListener que vai ser chamado do botão.

vini.roggia
Interface:
public interface IAtendimentoDAO {
public void insereNoBanco(AtendimentoBean atendimento);
}
Fabrica:
public class FabricaAtendimentoDAO {
public IAtendimentoDAO getAtendimentoDAO(){
        return new AtendimentoDAOImpl();
}
}

Implementação:

class AtendimentoDAOImpl implements IAtendimentoDAO{
public void insereNoBanco(AtendimentoBean Atendimento) {
        try {
          ConfigBean c = conexao();

          String nome = c.getNome();
          String url = c.getUrl();
          Connection conn = null;
          Class.forName(nome);
          conn = DriverManager.getConnection(url);

          try{
          String sql = "insert into Atendimento values(?,?,?,?,?,?,?,?,?)";

          String sqlCont = "select * from atendimento where chamado = (select max(chamado) from atendimento)";

          PreparedStatement ps = conn.prepareStatement(sql);
          PreparedStatement cont = conn.prepareStatement(sqlCont);

          ResultSet rs = cont.executeQuery();
          int numeroChamados=0;
          while(rs.next()){
          numeroChamados = rs.getInt("chamado");
          }
          //numMais é o valor máximo encontrado
          int numMais = numeroChamados + 1;

          ps.setInt(1, numMais);
          ps.setString(2, Atendimento.getSolicitante());
          ps.setString(3, Atendimento.getDepartamento());
          ps.setString(4, Atendimento.getDataSolicitacao());
          ps.setString(5, Atendimento.getSolicitacao());
          ps.setString(6, Atendimento.getCaracteristica());
          ps.setString(7, Atendimento.getDataAtendimento());
          ps.setString(8, Atendimento.getSolucao());
          ps.setString(9, Atendimento.getAtendente());

          ps.executeUpdate();

          } finally{
              conn.close();
          }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

Mais alguma coisa Mark?

Marky.Vasconcelos

Cade o ActionListener que deve atualizar a JTable?

vini.roggia

Como seria este ActionListener e em que classe ele deveria estar?

Marky.Vasconcelos

Onde esta implementado o actionPerformed que o botão que tem que listar vai ser chamado.

vini.roggia

Este é o botão na telaPrincipal:

private void btListarAbertoMousePressed(java.awt.event.MouseEvent evt) {                                            
// TODO add your handling code here:
    this.jogaNaTabelaAberto();
    spAtendimento.getVerticalScrollBar().setValue(tbAtendimento.getHeight());
       
}

E este é quem chama ele na classe telaCadastro:

private void btCadastrarMousePressed(java.awt.event.MouseEvent evt) {                                         
// TODO add your handling code here:
    if(this.taDescricao.getText().isEmpty() || this.tfNomeSolicitante.getText().isEmpty()){
        JOptionPane.showMessageDialog(null, "É obrigatório o preenchimento\nde todos os campos.");
    }
    else{
    FabricaAtendimentoDAO f = new FabricaAtendimentoDAO();
    IAtendimentoDAO a = f.getAtendimentoDAO();
            setAtendimento(new AtendimentoBean());
            getAtendimento().setSolicitante(this.tfNomeSolicitante.getText());
            getAtendimento().setDepartamento(this.cbDepartamento.getSelectedItem().toString());
            getAtendimento().setDataSolicitacao(this.jtfDataSolicitacao.getText());
            getAtendimento().setCaracteristica(this.cbCaracteristica.getSelectedItem().toString());
            getAtendimento().setSolicitacao(this.taDescricao.getText());

            a.insereNoBanco(getAtendimento());

            this.cbCaracteristica.setSelectedItem(0);
            this.taDescricao.setText("");
            
            JOptionPane.showMessageDialog(null, "Registro inserido", "Cadastro", 1);

            this.bt_listar_aberto.doClick();
            this.dispose();

        }
}
lina

Oi,

encontrei o problema.
Na classe TelaMenu, Não utilize para o btListarAberto o addMouseListener e sim AddActionListener. Ficando.:

btListarAberto.setText("Listar chamados em aberto");
        btListarAberto.addActionListener(
			new ActionListener(){
		        public void actionPerformed(ActionEvent e){			        	
				 this.jogaNaTabelaAberto();
    spAtendimento.getVerticalScrollBar().setValue(tbAtendimento.getHeight());		
		        }
	      });

Ainda na tela de Menu, na ação do seu MenuItem você estava fazendo assim.:

private void miNovoMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_miNovoMousePressed
	// TODO add your handling code here:
	TelaCadastro tc = new TelaCadastro();
	tc.setVisible(true);
}//GEN-LAST:event_miNovoMousePressed

Ou seja, chamando o construtor errado... deveria ser.:

private void miNovoMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_miNovoMousePressed
	// TODO add your handling code here:
	TelaCadastro tc = new TelaCadastro(btListarAberto);
	tc.setVisible(true);
}//GEN-LAST:event_miNovoMousePressed

Em sua TelaCadastro você estava fazendo confusão em seu construtor, invertendo as variaveis. Estava assim.:

TelaCadastro(JButton btListarAberto) {
        initComponents();

        this.setLocationRelativeTo(null);
       // this.setIconImage(Toolkit.getDefaultToolkit().getImage(TelaMenu.class.getResource("/helpdesk/icon.jpg")));
        DefaultComboBoxModel dcbm=(DefaultComboBoxModel) this.cbDepartamento.getModel();

        System.out.println(btListarAberto == null);//esta dando false
        btListarAberto = bt_listar_aberto; //Recebe o botão parametrizado
        btListarAberto.doClick();
        if(pressionado==1)
        dispose();
    }

e deveria estar assim.:

TelaCadastro(JButton btListarAberto) {
        initComponents();

        this.setLocationRelativeTo(null);
       // this.setIconImage(Toolkit.getDefaultToolkit().getImage(TelaMenu.class.getResource("/helpdesk/icon.jpg")));
        DefaultComboBoxModel dcbm=(DefaultComboBoxModel) this.cbDepartamento.getModel();

        System.out.println(btListarAberto == null);//esta dando false
        bt_listar_aberto = btListarAberto; //Recebe o botão parametrizado
        bt_listar_aberto.doClick();
        if(pressionado==1)
        dispose();
    }

Era isso!

Tchauzin!

vini.roggia

Lina,

Sem palavras, era isso mesmo, adicionando aquele ActionPerformed e colocando bt_listar_aberto.doClick();

tanto no contrutor como no evento de mouse pressionado do botão Cadastrar funcionou perfeitamente.

Queria apenas tirar as ultimas duvidas. Por que foi necessário colocar o bt_listar_aberto.doClick();

em ambos(construtor e evento) para funcionar? E como funciona, qual função do ActionPerformed ?

Gostaria de agradecer a atenção de todos e a ajuda, a qual cada dia que venho, aprendo algo novo.

lina

vini.roggia:
Lina,

Sem palavras, era isso mesmo, adicionando aquele ActionPerformed e colocando bt_listar_aberto.doClick();

tanto no contrutor como no evento de mouse pressionado do botão Cadastrar funcionou perfeitamente.

Queria apenas tirar as ultimas duvidas. Por que foi necessário colocar o bt_listar_aberto.doClick();

em ambos(construtor e evento) para funcionar? E como funciona, qual função do ActionPerformed ?

Gostaria de agradecer a atenção de todos e a ajuda, a qual cada dia que venho, aprendo algo novo.

Oi,

O ActionListener não é nada + do que uma Interface que fica escutando todas as ações/eventos recebidos. Quando é detectado qualquer ação, o método actionPerformed é chamado. E será nele que você deverá tratar essas ações.

Quando você chamou a outra classe (TelaCadastro) passando o botão, era apenas para ter uma referencia do botão criado na classe principal. Tendo essa referencia, você poderia chamar esse actionPerformed criado na classe principal, executando o método doClick(). OBS.: O método doClick() executa um “pressed” no botão sem ter interferencia do usuário (faz o click automatico)

Fico feliz que funcionou! Apenas edit seu primeiro posto e coloque a tag [RESOLVIDO] para o pessoal não ficar entrando, sendo que o tópico está resolvido.

Tchauzin!

Marky.Vasconcelos

Nossa… duvida dificil essa de resolver.

E de qualquer modo. Não é necessario o doClick no construtor. Voce não precisa listar ao criar a outra tela e sim quando clicar no botão apenas.

D

Vini, mesmo tendo dado certo deste modo, te aconselho a utilizar o padrão Observer cara.
Vc vai ver que ele será mto útil e acontecerá de vc utilizá-lo diversas vezes.

vini.roggia

Bom dia pessoal,

Mark, obrigado pela ajuda, foi de muita valia a sua participação. Tive muita dificuldade para resolver o problema, é só olharmos para o número de posts.
Sobre o doClick no construtor vou verificar onde pode estar o erro, pois testei sem ele e não funcionou, realmente não entendo porque ele teria de estar ali.

Danilo, obrigado também por tudo e pela a indicação de estudo, vou mesmo seguir o seu conselho, pesquisei na internet e este padrão Observer é muito utilizado.

lina

Oi,

Apenas uma observação.:

-> O doClick() não precisa estar dentro do construtor e sim logo após executar o método para inserir um novo registro.

Tchauzin!

Criado 15 de julho de 2009
Ultima resposta 20 de jul. de 2009
Respostas 71
Participantes 10