Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java swing GUI freezes

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?

like image 237
Nick Sanders Avatar asked Jun 25 '12 08:06

Nick Sanders


3 Answers

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.
like image 189
GETah Avatar answered Sep 21 '22 10:09

GETah


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

like image 31
Vedant Agarwala Avatar answered Sep 23 '22 10:09

Vedant Agarwala


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

like image 22
CosminO Avatar answered Sep 21 '22 10:09

CosminO