Java Swing Gui Freezes

Java swing GUI freezes

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.

Java Swing GUI updating/changing from method - freezing in loop

You're correct in thinking that it related to threads.

When you try executing code that will take a long time to process (eg. downloading a large file) in the swing thread, the swing thread will pause to complete execution and cause the GUI to freeze. This is solved by executing the long running code in a separate thread.

As Sergiy Medvynskyy pointed out in his comment, you need to implement the long running code in the SwingWorker class.

A good way to implement it would be this:

public class TestWorker extends SwingWorker<Integer, String> {

@Override
protected Integer doInBackground() throws Exception {
//This is where you execute the long running
//code
controller.startTest(index, idUser);
publish("Finish");
}

@Override
protected void process(List<String> chunks) {
//Called when the task has finished executing.
//This is where you can update your GUI when
//the task is complete or when you want to
//notify the user of a change.
}
}

Use TestWorker.execute() to start the worker.

This website provides a good example on how to use
the SwingWorker class.

Swing GUI freezes

I don't think your GUI is freezing, it's just not been told to change. Have you tried calling repaint() on the frame after the ChartPanel is added?

As regards threads, if the code inside actionPerformed is less than instant, you should probably do it in a separate thread.

Swing Multithreading. My GUI is freezing

You might actually have to launch a new Thread, so the blocking operations do not affect your application GUI too much. However, operations within that update the GUI should be executed by the original Event Dispatch Thread.

As pointed in other answers, here the main offender seems to be the use of Thread.sleep(). Which when executed in the Event Dispatch Thread will cause the GUI to become irresponsive (won't accept your input or redraw until it has finished executing your event listener code). However that Thread.sleep() is acceptable if used in other Threads (which wont freeze your GUI).

How to do it

First: Launch your blocking handling code in a separate Thread.

public void actionPerformed(ActionEvent e) {
if ((e.getActionCommand()).equals("spam1")) {
new Thread(){
@Override
public void run() {
try {
Spambot.Start("data/firstfile.txt");
} catch (FileNotFoundException | InvocationTargetException |
AWTException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
// ... rest of conditions

}

Second, every individual GUI update between delays, should be done in the Event Dispatch Thread.

EventQueue.invokeAndWait(new Runnable(){
public void run() {
robot.keyPress(KeyEvent.VK_ALT);
};
});

As all the updates done are in robot.keyPress() invocations, a good choice might be to encapsulate and re-use in a method. Note that local variables and arguments that are used inside inner class should be defined as final (so they are made available outside the stackframe of the method)

private static void invokeRobotInAWT(final Integer ... ke) throws InvocationTargetException, InterruptedException {
EventQueue.invokeAndWait(new Runnable(){
public void run() {
for (int currentEvent : ke) {
robot.keyPress(currentEvent);
}
};
});
}

public static void Start(String path) throws AWTException, InterruptedException, FileNotFoundException, InvocationTargetException {
try (Scanner input = new Scanner(new FileReader(path));) {
Spambot keyboard = new Spambot();
Random rand = new Random();
invokeRobotInAWT(KeyEvent.VK_ALT);
Thread.sleep(150);
invokeRobotInAWT(KeyEvent.VK_TAB);
Thread.sleep(150);
invokeRobotInAWT(KeyEvent.VK_TAB, KeyEvent.VK_ALT);
Thread.sleep(500);
while (input.hasNextLine() && !stopped) {
// @@@ Would need extra threading here?
keyboard.type(input.nextLine());
Thread.sleep(rand.nextInt(1500)+1000);
invokeRobotInAWT(KeyEvent.VK_ENTER, KeyEvent.VK_ENTER);
}
} finally {
// input closed by try-with-resources
}
}

Edited: Oops. I got it wrong with SwingWorker. Might actually be adequate.

Note: There are helper components in Swing that might spare us from complex and error-prone thread handling. You might actually use a SwingWorker where your overridden doInBackground() method (in the worker thread) traverses the file, does the pauses, and sends the keystrokes (call publish(Integer)), to be processed by the EDT in the overridden process(List<Integer>) method.



Related Topics



Leave a reply



Submit