domingo, 24 de outubro de 2010

Swing: Comunicação entre duas janelas distintas

Algumas vezes é necessário realizar uma conversa básica entre duas janelas, para isso podemos adotar algumas soluções:
Janelas em projetos diferentes:
1 - Comunicação por arquivo/banco de dados.
    > Ao serem instanciadas, as janelas devem iniciar uma Thread que fica varrendo a cada x tempo o arquivo ou banco de dados, a procura de novas informações.
    > Quando alguma das janelas quiser enviar uma mensagem para a outra, basta gravar a informação no arquivo/banco de dados.
    > Dica: Junto com a mensagem, grave também algum ID ou Código que identifique qual janela deve ler aquela mensagem, caso contrário todas as janelas, inclusive a que enviou a mensagem, recolherão as informações.
2 - Comunicação via Sockets.
      Funciona da mesma forma que a comunicação por arquivos/banco de dados, porém neste caso deve-se trabalhar com sockets e computadores diferentes, a comunicação só pode ser feita entre duas janelas, e uma deve saber o ip da outra, as Threads iniciadas ficam responsáveis por recepcionar os pacotes de dados enviados. Para efetuar a comunicação com mais janelas, é necessário possuir um "servidor" que fica recebendo as mensagens de todo mundo e as repassando, neste caso as janelas precisam saber apenas o ip do "servidor".
Janelas em um mesmo projeto:
1 - Comunicação direta!
      Trabalhando com janelas em um mesmo projeto, a comunicação pode ser direta, ou seja, uma janela pode acessar os métodos ou objetos da outra, desde que estes estejam definidos como public e/ou static. Porém, para que isso se torne possível, ambas as janelas precisam ser iniciadas de um mesmo lugar (uma única classe que inicia as duas janelas, mesmo que em momentos distintos), ou uma das janelas inicie a Fazendo isso elas estarão instanciadas em uma mesma "rua" na jvm e uma enxergará a outra.
Para ilustrar um pouco mais, segue o exemplo abaixo onde possuímos três classes: ChamaOsDois, JanelaUm eJanelaDois.
Funciona da seguinte maneira, a classe ChamaOsDois inicia as duas janelas, a JanelaUm recebe as informações enviadas pela JanelaDois.
Para a mágica acontecer, a JanelaUm deve ter seu frame marcado como estático e possuir algum método public que acessa os objetos internos. A classe JaneDois simplesmente cria uma referência para a JanelaUm (uma instância sem a palavra new), e acessa o método publico da JanelaUm. Neste caso,  comunicação da JanelaDois para a JanelaUm deve ser mediada pela classe ChamaOsDois, uma vez que foi essa classe que instanciou as duas janelas, para casos em que uma janela inicia a outra não é necessário esse mediador.
public class JanelaUm extends javax.swing.JFrame{ 
//Inicialização dos Objetos  
private javax.swing.JLabel labelEscreva; 
private javax.swing.JTextArea txtAreaRecebedor = new javax.swing.JTextArea(); 
public static JanelaUm frame; 
//Construtor
public JanelaUm(){ 
super("Janela UM - TextArea Recebedor"); 
        constroiTela(); 
    } 
   //Método de construção de janela
private void constroiTela(){ 
this.setLayout(null); 
this.setSize(300,300); 
this.setPreferredSize(getSize()); 
labelEscreva = new javax.swing.JLabel("TextArea Recebedor:"); 
labelEscreva.setBounds(10,20,250,20); 
labelEscreva.setVisible(true); 
        this.add(labelEscreva); 
txtAreaRecebedor.setBounds(10,50,270,210); 
txtAreaRecebedor.setLineWrap(true); 
txtAreaRecebedor.setVisible(true); 
txtAreaRecebedor.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0,0,0), 1,false)); 
        this.add(txtAreaRecebedor); 
    } 
//Este método está marcado como public para poder ser acessado de outras classes 
    //ele recebe uma string e adiciona ao TextArea. 
public void adicionaTexto(String msg){ 
txtAreaRecebedor.append(msg + "\n"); 
    } 
}
public class JanelaDois extends javax.swing.JFrame{ 
//Criação dos objetos
private javax.swing.JLabel labelEscreva; 
private javax.swing.AbstractAction action2OK; 
private javax.swing.JTextField txtEscreva; 
private javax.swing.JButton btnOk; 
//Aqui estou criando uma referencia ao frameUm da classe pai ChamaOsDois, esta variável da classe 
    //ChamaOsDois já está fazendo referencia ao frame da classe JanelaUm, então esta variável 
    //janelaUm recebe a referencia da propria classe JanelaUm. 
    //Note que nem aqui, nem na classe ChamaOsDois estou indicando a palavra "new" por que não quero 
    //criar uma nova instancia, mas apenas pegar a referencia do objeto que já está criado. 
    JanelaUm janelaUm = ChamaOsDois.frameUm
//Construtor
public JanelaDois(){ 
super("Janela Dois - Escreva algum texto"); 
        constroiJanela(); 
    } 
//Método de construção da janela
private void constroiJanela(){ 
this.setSize(300,125); 
this.setPreferredSize(getSize()); 
this.setLayout(null); 
labelEscreva = new javax.swing.JLabel("Escreva algo e clique em OK:"); 
labelEscreva.setBounds(10, 20, 250, 20); 
labelEscreva.setVisible(true); 
txtEscreva = new javax.swing.JTextField(); 
txtEscreva.setBounds(10, 40, 270, 20); 
txtEscreva.setVisible(true); 
btnOk = new javax.swing.JButton("OK"); 
btnOk.setText("OK"); 
btnOk.setBounds(120,65,60,20); 
btnOk.setAction(getAction2OK()); 
btnOk.setVisible(true); 
        this.add(labelEscreva); 
        this.add(txtEscreva); 
        this.add(btnOk); 
    } 
//Ação do botão "OK" 
private javax.swing.AbstractAction getAction2OK() { 
        if(action2OK == null) { 
            action2OK = new javax.swing.AbstractAction("OK", null) { 
public void actionPerformed(java.awt.event.ActionEvent evt) { 
  //Verifica se a variavel está nula, se estiver tenta pegar a 
                    //referencia novamente.

                    if(janelaUm == null){ 
janelaUm = ChamaOsDois.frameUm
                    } 
//chama o método adicionaTexto da classe JanelaUm e informa o que foi 
                    //digitado no txtEscreva desta janela.

janelaUm.adicionaTexto(txtEscreva.getText()); 
txtEscreva.setText(""); 
                } 
            }; 
        } 
return action2OK; 
    } 
}
public class ChamaOsDois { 
//Referencia da JanelaUm, marcada como public static para poder ser 
    //referenciada de outras classes que iniciarem a partir deste ponto  

public static JanelaUm frameUm; 
public static void main(String[] args){ 
//Criação da JanelaUm 
frameUm = new JanelaUm(); 
frameUm.setLocationRelativeTo(null); 
frameUm.pack(); 
frameUm.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); 
frameUm.setVisible(true); 
//Criação da JanelaDois
        JanelaDois frameDois = new JanelaDois(); 
frameDois.setLocationRelativeTo(null); 
frameDois.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); 
frameDois.setVisible(true); 
    } 
}
Neste exemplo, coloque as três classes em um mesmo local e execute a classe ChamaOsDois.

0 comentários:

Postar um comentário

Alguma dúvida?

 

© 2009Java Erro | by TNB