Chamando metodos

4 respostas
X

:frowning:
Ola a todos! meu problema é o seguinte, escrevi um programa simples de mensagens com sockets. No arquivo Client.java ha um o metodo runClient() que é chamado no metodo main iniciando a conexao com o servidor na execucao do programa, ate ai tudo bem, porem quando tendo associar o metodo runClient() ha um evento de um JButton definido dentro do Construtor nao funciona corretamente. Ao clicar no botao ele se conecta ao servidor mas o JButton nao retorna ao seu estado inicial, ele fica pressionado. segue o codigo iniciado :

import java.io.*;
import java.awt.*;
import java.net.*;
import javax.swing.*;
import java.awt.event.*;


public class Client extends JFrame
{
   private JTextField texto;
   private JTextArea display;
   private JButton conectar;
   ObjectOutputStream saida;
   ObjectInputStream entrada;
   UIManager.LookAndFeelInfo looks[];
//****************************************************************
   public Client()
   {
     super("Cliente");
    
     looks = UIManager.getInstalledLookAndFeels();		
	 try 
    {
        UIManager.setLookAndFeel( looks[ 0 ].getClassName() );
        SwingUtilities.updateComponentTreeUI( this );
    }
    catch ( Exception e ) 
    {
         e.printStackTrace();
    }
     
     Container c = getContentPane();
     JPanel p = new JPanel(new GridLayout(1,2));
     
     texto = new JTextField();
     texto.setEnabled(false);
     //texto.setForeground(color.BLUE)
     texto.addActionListener(
     new ActionListener()
     {
       public void actionPerformed(ActionEvent e) 
       {
         sendData(e.getActionCommand());
       }
     }  
     );

///PROBLEMA ESTA QUANDO CHAMA O METODO ASSIM

     conectar = new JButton("Conectar");
     conectar.addActionListener(
     new ActionListener()
     {
       public void actionPerformed(ActionEvent e) 
       {
         runClient();
       }
     }  
     );


     p.add(conectar);
     p.add(texto);
     c.add( p, BorderLayout.NORTH);
     display = new JTextArea();
     c.add(new JScrollPane(display), BorderLayout.CENTER);
     
     setSize(400,250);
     show();
     
   }
//**************************************************************** 

   public void runClient()
   {
     Socket cliente;
     
    try
    {
     
       display.setText("Cliente conectando
");
       cliente = new Socket(InetAddress.getByName("127.0.0.1"),5000);
       
       display.append("Conectado ao " + cliente.getInetAddress().getHostName());     
                               
       saida = new ObjectOutputStream(
                   cliente.getOutputStream());
       saida.flush();
       entrada = new ObjectInputStream(
                     cliente.getInputStream());
       display.append("
 I/O Streams foi pega
");

       texto.setEnabled(true);
       

       String message = "";
       do
       {
         try
         {
           message = (String) entrada.readObject();
           display.append("
" + message);
           display.setCaretPosition(display.getText().length());
         }
         catch(ClassNotFoundException cnfex)
         {
           display.append("
 Tipo de Objeto recebido Desconhecido");
         }
       }while(!message.equals("SERVIDOR>> TERMINAR"));
      
       display.append("
 Fechando conexao
");
       saida.close();
       entrada.close();
       cliente.close();
          
   }
   catch(EOFException eof)
   {
     System.out.println("Servidor terminou conexao");
   }
   catch(IOException io)
   {
     io.printStackTrace();
   }
 }
//****************************************************************
 
  private void sendData(String s)
  {
    try
    {
      saida.writeObject("CLIENTE>> " + s);
      saida.flush();
      display.append("
CLIENTE>> " + s ); 
      texto.setText("");
    } 
    catch(IOException cnfex)
    {
      display.append("
Erro ao escrever o objeto") ;
    }
  }
//****************************************************************
  public static void main(String args[])
  {
    Client app = new Client();
    
    app.addWindowListener(
      new WindowAdapter()
      {
        public void windowClosing(WindowEvent e) 
        {
          System.exit(0);
        }
      }
    );

//QUANDO E CHAMADO DESTE FORMA NAO HA PROBLEMA
//   app.runClient();
  }
   
}

4 Respostas

lalgarve

Oi Xela!

O problema é o seguinte: enquanto o listener não chega ao fim nada na tela é atualizado. Todas as tarefas que um listener faz tem que ser rapidas. Quando é necessário fazer uma tarefa longa tem-se que fazê-la em outro Thread. Mais um detalhe, quando se atualizar a tela fora de um listener deve-se usar os metodos invokeAndWait ou invokeLater da classe javax.swing.SwingUtilities. Se você não usar um desses métodos, pode até não ter problema, mas não é recomendado. Veja a URL abaixo:
[URL]http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html[/URL]

Você pode implementar o que eu disse, utilizando uma classe interna privada da seguinte maneira:

private class RunClient extends Thread
{
    //creio que saida e entrada sao utilizados apenas nesta classe interna
    ObjectOutputStream saida; 
    ObjectInputStream entrada; 

    public void run()
    {
    // o código do método runClient entra aqui
    // de preferencia modificado para utilizar SwingUtilities
    }

   private void sendData(String s) 
   {
    // código do método sendData
    // de preferencia modificado para utilizar SwingUtilities
   }
}

O listener fica da seguinte maneira:

conectar = new JButton("Conectar"); 
conectar.addActionListener( 
new ActionListener() 
{ 
   public void actionPerformed(ActionEvent e) 
  { 
       new RunClient().start();   
  } 
} 
);

Espero que isto resolva o problema.

X

:slight_smile: Leila muito obrigado

X

lalgarve

essa thread executa e morre dentro do listener ?

por algum motivo caso nao for feita a conexao ela nao ficara ocupando memoria e processando no processador?

lalgarve

Eu não diria que a thread é executada dentro do listener. Quando o método “start” é chamado apenas se diz que a thread pode começar a execução. Não importa quanto tempo demora para a thread chegar ao fim, quando se chama o método “start”, a execução do programa prossegue logo em seguida. O listener não vai esperar a thread terminar.

Assim que o método “run” chegar ao fim, a thread termina, não consome mais processador e se não houver nenhuma referência a ela, ela fica disponível para ser retirada da memória. Não importa se houve erro ou não. O importante é o método “run” chegar ao final (eu não verifiquei o seu código prestando tanta atenção ao ponto de verificar se isso acontece).

Xela, se este programa for crescer, creio que vai ser necessário separar totalmente o código de conecção com o servidor do código de atualização da tela. Você pode fazer com que RunClient “avise” o objeto responsável pela tela quando dados chegam do servidor, se ocorreu erro, quando a conecção terminar, etc. Você pode usar para isso a interface java.util.Observer e a classe java.util.Observable. A url abaixo explica um pouco, em português. Em ingles é fácil de encontrar. O próprio javadoc da Sun explica um pouco.
http://www.argonavis.com.br/cursos/java/j930/

Criado 29 de março de 2003
Ultima resposta 30 de mar. de 2003
Respostas 4
Participantes 2