Java swing GUI freezes

12,504

Solution 1

You have two pitfalls in your design:

  1. ss.accept() is a blocking call so your UI will freeze until there is an incoming connection
  2. Never run while(true) loops in the EDT.

Instead do the following:

  • When the button is clicked create a thread that will start listening for incoming connections.
  • Whenever you have an incoming connection, create another thread that will take the incoming client connection and deal with it.

Solution 2

as long as your

new socket(ss.accept());

returns immediately, you only need to change your

while (true)

this puts the EDT (Event Dispatch Thread) into an infinite loop and your GUI becomes irresponsive. So, delete this line.

If you can't then use the SwingWorker class ( http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html#process(java.util.List) Create a nested class that extents SwingWorker. Just call a swingWoker.execute(); (after you have created its object) in your listenButtonActionPerformed(java.awt.event.ActionEvent evt) method.

See the tutorial: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

Never create a new thread and run it from from the Swing EDT

Solution 3

Check this out: http://javarevisited.blogspot.ro/2012/02/what-is-blocking-methods-in-java-and.html

1) If you are writing GUI application may be in Swing never call blocking method in Event dispatcher thread or in the event handler. for example if you are reading a file or opening a network connection when a button is clicked don't do that on actionPerformed() method, instead just create another worker thread to do that job and return from actionPerformed(). this will keep your GUI responsive, but again it depends upon design if the operation is something which requires user to wait than consider using invokeAndWait() for synchronous update.

Using multiple threads: http://javarevisited.blogspot.ro/2011/02/how-to-implement-thread-in-java.html

Solution 4

You will need to use Multi-Threading. If I where you, I would separate the GUI code and the server code and when the button is pressed, I simply launch the Server code as a new Thread.

Your code is freezing the GUI basically because all events are executed on the Event Dispatcher Thread (EDT) which is the thread which takes care of all your GUI stuff and respective events. If you either block it, stop it or throw in loops it will affect on its performance.

Solution 5

Try these...

1. During getting the initial connection delay can occur, so first create and empty socket,then try to connect to the server.

   `Socket s = new Socket();`

   `s.connect(new InetSocketAddress("ip_addr",port_nos),1000);`

2. And Secondly always keep the Non-UI work out of Your UI thread..

Here is my Example of Server - Client Communication..

Client side code:

public class ClientWala {

    public static void main(String[] args) throws Exception{

        Boolean b = true;
    Socket s = new Socket();
    s.connect(new InetSocketAddress("127.0.0.1", 4444),1000);

    System.out.println("connected: "+s.isConnected());


    OutputStream output = s.getOutputStream();
    PrintWriter pw = new PrintWriter(output,true);

    // to write data to server
    while(b){

        if (!b){

             System.exit(0);
        }

        else {
            pw.write(new Scanner(System.in).nextLine());
        }
    }


    // to read data from server
    InputStream input   = s.getInputStream();
    InputStreamReader isr = new InputStreamReader(input);
    BufferedReader br = new BufferedReader(isr);
    String data = null;

    while ((data = br.readLine())!=null){

        // Print it using sysout, or do whatever you want with the incoming data from server

    }




    }
}

Server side code:

import java.io.*
import java.net.*;


public class ServerTest {

    ServerSocket s;

    public void go() {

        try {
            s = new ServerSocket(44457);

            while (true) {

                Socket incoming = s.accept();
                Thread t = new Thread(new MyCon(incoming));
                t.start();
            }
        } catch (IOException e) {

            e.printStackTrace();
        }

    }

    class MyCon implements Runnable {

        Socket incoming;

        public MyCon(Socket incoming) {

            this.incoming = incoming;
        }

        @Override
        public void run() {

            try {
                PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
                        true);
                InputStreamReader isr = new InputStreamReader(
                        incoming.getInputStream());
                BufferedReader br = new BufferedReader(isr);
                String inp = null;

                boolean isDone = true;

                System.out.println("TYPE : BYE");
                System.out.println();
                while (isDone && ((inp = br.readLine()) != null)) {

                    System.out.println(inp);
                    if (inp.trim().equals("BYE")) {
                        System.out
                                .println("THANKS FOR CONNECTING...Bye for now");
                        isDone = false;
                        s.close();
                    }

                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                try {
                    s.close();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }

        }

    }

    public static void main(String[] args) {

        new ServerTest().go();

    }

}
Share:
12,504
Nick Sanders
Author by

Nick Sanders

Updated on June 04, 2022

Comments

  • Nick Sanders
    Nick Sanders almost 2 years

    I am writing a Java client/server GUI application using sockets and here is the problem:

    I have a button to start listening for a specified port:

    button actionPerformed method

    private void listenButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             
        int port = Integer.parseInt(portTextfield.getText(), 10);
    
        try {
            socket.listen(port);
        } catch (IOException ex) {
        }
    }
    

    Here is the socket.listen method

    public static void listen() throws IOException {
        ServerSocket ss = new ServerSocket(port);
    
        while (true)
            new socket(ss.accept());
    }
    

    "socket" class extends "Thread"
    So after ss.accept() returns a value it creates new socket instance in separate thread.

    After clicking the button the GUI freezes because inside the socket.listen method there is an infinite loop. How can I avoid that?