Meu primeiro tutorial [Passando valores para outro JFrame]

Olá pessoal,

Já foi minha dúvida, e continua sendo de muita gente. Eu me perguntava de que forma eu poderia enviar e receber valores de um outro JFrame qualquer. Então está aí meu primeiro tutorial.
Como sou iniciante, peço que, se alguem conseguir fazer de uma forma melhor que tbm compartilhe.

Arquivo Main :: Esse arquivo não tem segredo, ele é o main principal, instanciando a JanelaPrincipal e JanelaSecundaria, ambos(JFrame)

public class Main {

    public static void main(String[] args) {
        JanelaPrincipal janelaPrincipal = new JanelaPrincipal(); //faz a instancia
        janelaPrincipal.setVisible(true); // mostra a janelaPrincipal

        JanelaSecundaria janelaSecundaria = new JanelaSecundaria(); // faz a instância
        janelaSecundaria.instancia(janelaPrincipal); // janelaSecundaria possui um método que recebe a instância da 'janelaPrincipal', no qual a gente precisa para enviar os valores mais tarde. 
        janelaSecundaria.setVisible(true); // mostra a janelaSecundaria
    }
}

Arquivo JFrame JanelaPrincipal :: No fonte do JFrame JanelaPrincipal, ou seja, o JFrame que vai receber o valor.

    public void campoRecebe(String Txt){  // Esse método vai inserir o valor que é recebido pelo parâmetro.
        jTextField1.setText(Txt); // e inserir em um campo de texto jTextField.
    }

Arquivo JFrame JanelaSecundaria :: No fonte do JFrame JanelaSecundaria, ou seja, o JFrame que vai enviar o valor.


    javax.swing.JFrame jframe; // Reservo uma instância que será recebida pelo método 'public void instancia()'.

    public void instancia(javax.swing.JFrame jframe){
        this.jframe = jframe; // Guarda o valor recebido pelo parâmetro.
    }


    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { // Método que, ao clicar no botão, envia.
        JanelaPrincipal janelaPrincipal = (JanelaPrincipal)this.jframe; // Aqui acontece toda mágica, e feito um CAST(é isso pessoal ?)
        janelaPrincipal.campoRecebe(jTextField1.getText()); // Chama o método que está na 'janelaPrincipal'
        jTextField1.setText(null);
    }

Bem, é isso aí pessoal. Espero ter dado uma luz.

Obrigado.

Por que não deixar a janela secundária ter um atributo do tipo JanelaPrincipal direto? Aí vc não precisa de cast.

Na verdade, a melhor maneira de organizar essas duas janelas, sem acopla-las demais, seria através do padrão observer.

Para isso:

  1. Crie uma interface que irá receber o evento da janela secundária:

public interface JanelaSecundariaListener { //No caso, esse método transmite um texto void textoDefinido(String texto); }

  1. No lugar do método instância, crie um método para receber o listener. E no actionPerformed, chame o listener.
//No lugar de deixar um JFrame, deixe uma instância do listener
private JanelaSecundariaListener listener = null;

//No lugar do método instância, faça um método para definir o listener
public void setListener(JanelaSecundariaListener listener) {
    this.listener = listener;
}

//No actionPerformed, chame o listener.
//Note que essa janela não sabe o que o listener fará com a informação, o que é bom.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { // Método que, ao clicar no botão, envia.  
   listener.textoDefinido(jTextField1.getText()); //Chama o método do listener
   jTextField1.setText(null);  
}  
  1. Na janela principal, implemente a interface JanelaSecundariaListener e, no lugar do método campoRecebe, use o método do Listener:

public JanelaPrincipal implements JanelaSecundariaListener { ... @Override public void textoDefinido(String txt){ // Esse método vai inserir o valor que é recebido pelo parâmetro. jTextField1.setText(txt); // e inserir em um campo de texto jTextField. } }

  1. No seu main, defina a janela principal como listener da secundária:

[code]public class Main {
public static void main(String[] args) {
JanelaPrincipal janelaPrincipal = new JanelaPrincipal(); //faz a instancia
janelaPrincipal.setVisible(true); // mostra a janelaPrincipal

    JanelaSecundaria janelaSecundaria = new JanelaSecundaria(); // faz a instância
    // janelaSecundaria possui um método que recebe a instância de um JanelaSecundariaListener, 
    //a qual receberá os dados mais tarde. Como a janela principal implementa essa interface, ela pode 
    //ser adicionada aqui. 
    janelaSecundaria.setListener(janelaPrincipal); 
    janelaSecundaria.setVisible(true); // mostra a janelaSecundaria
}

}[/code]

A vantagem dessa abordagem é que também não tem o cast, e não cria dependência da janela principal na secundária. Note que a janela secundária poderia enviar o dado para qualquer objeto, inclusive um que nem sequer fosse uma janela. Basta que ele implemente a interface JanelaSecundariaListener.

Claro, outra forma de comunicar dados entre janelas ainda mais simples é usando um JDialog. A vantagem dos dialogs é que, quando são modais, o comando setVisible “trava” e fica parado até que a janela seja fechada. Isso simplifica muito a troca de dados, como pode ser visto nesse exemplo:
http://www.guj.com.br/java/55710-comunicacao-de-dados-entre-duas-janelas#292687

Bacana Vini, eu não sabia como usar o Listener =)… Agora sei…

Vlw…

Sim, isso mostra como criar seu próprio listener. :slight_smile:
E a importância do uso de interfaces para separar as camadas do sistema.

No exemplo aí, a interface dá a JanelaSecundaria uma garantia: De que quem irá escutar por seus eventos implementa o método textoDefinido. E é só isso que a JanelaSecundaria precisa saber. Ela não precisa saber quem é esse alguém, nem o que faz depois que o método é chamado.

Desculpe por desenterrar isso aqui, mas vim através de um outro problema postado por um usuário que estava se baseando no exemplo do ViniGodoy.

Corrija-me se eu estiver errado, mas no item 3 você diz para implementar a interface na classe da JanelaPrincipal, porém você está estendendo a interface em uma classe e isso não é possível, creio eu.

Caso eu não tenha entendido, peço que desconsidere o que falei, mas se eu estiver correto, por favor corrija isso, pois está gerando problemas entre os usuários que estão utilizando seu exemplo

Abraço

Sim, o certo era colocar implements, e não extends.

Mas acho um pouco extremo dizer que isso “gera problemas”. Usuários do GUJ tem que entender o conceito e implementa-los eles mesmos. Não podem esperar que todo código postado aqui esteja 100% correto, até porque poucos irão abrir o eclipse para compilar e então postar.

Boa parte do código do fórum é escrito de cabeça, para dar uma noção geral da solução. Muitas vezes há variáveis no código que pressupomos existir, ou campos que precisariam ser substituídos. Jamais tente usar códigos daqui a base do copy&paste.

Em todo caso, corrigi a postagem lá em cima.

Creio que o meu “gera problemas” não foi bem entendido. Concordo com você que eles devem ter os conceitos já entendido, mas alguns não se sentem seguros com o que sabem e se espelham nos mais experientes. Os problemas a que me referia é o dos usuários que copiam e depois vem tirar suas dúvidas gerando conteúdo desnecessário.

Mas de qualquer forma obrigado por corrigir.

Abraço

Funcionou perfeitamente para mim!

Valeu ViniGodoy!!

[quote=filipi_saci]Funcionou perfeitamente para mim!

Valeu ViniGodoy!![/quote]

De nada.

Evite ressuscitar postagens muito antigas à toa. Tive que reler o tópico inteiro para entender sobre qual assunto de 3 anos atrás vc estava falando… hehehehe