Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java's Swing Threading

My understanding is that if I start up another thread to perform some actions, I would need to SwingUtilities.invokeAndWait or SwingUtilities.invokeLater to update the GUI while I'm in said thread. Please correct me if I'm wrong.

What I'm trying to accomplish is relatively straightforward: when the user clicks submit, I want to (before performing any actions) disable the submit button, perform the action, and at the end of the action re-enable the button. My method to perform the action updates the GUI directly (displays results) when it gets the results back.

This action basically queries a server and gets some results back.

What I have so far is:

boolean isRunning = false;

synchronized handleButtonClick() {
  if ( isRunning == false ) {
    button.setEnabled( false );
    isRunning = true;
    doAction();
  }
}

doAction() {
  new Thread() {
    try {
      performAction(); // Concern A
    } catch ( ... ) {
      displayStackTrace( ... ); // Concern B
    } finally {
      SwingUtilities.invokeLater ( /* simple Runnable to enable button */ );
      isRunning = false;
    }
  }
}

For both of my concerns above, do I would have to use SwingUtilities.invokeAndWait since they both will update the GUI? All GUI updates revolve around updating JTextPane. Do I need to in my thread check if I'm on EDT and if so I can call my code (regardless of whether it updates the GUI or not) and NOT use SwingUtilities.invokeAndWait?

EDIT: Here is what I am doing now:

handleButtonClick() {
  if ( isRunning == true )
     return;
  disable button;
  SwingWorker task = new MyTask();
  task.execute();
}

...inside MyTask
doInBackground() {
  return performAction();
}

done() {
  result = get();
  enable button;
  isRunning = false;
  interpret result (do most of the GUI updates here);
}

While performAction() does some GUI updates, I have wrapped those in:

if ( SwingUtil.isEDT() )
  doGUIupdate()
else
  SwingUtil.invokeLater( new Runnable() {
    run() {
      doGUIupdate();
    }
  } );

Hopefully this is a step in the right direction, please comment if you believe there are better ways to handle my situation.

like image 744
nevets1219 Avatar asked Apr 02 '10 00:04

nevets1219


People also ask

Is Swing thread safe in Java?

No, Java Swing components are not thread-safe in Java.

Is Java Swing multi threaded?

This means that most Swing components are, technically, not threadsafe for multithreaded applications. Now don't panic: it's not as bad as it sounds because there is a plan. All event processing in AWT/Swing is handled by a single system thread using a single system event queue. The queue serves two purposes.

Is Java Swing single threaded?

Swing is single-threaded.

Is Java Swing still used in 2021?

Absolutely yes. Legacy swing applications are still supported and enhanced. There is no alternative for that.


2 Answers

In my opinion you should almost never use invokeAndWait(). If something is going to take awhile that will lock your UI.

Use a SwingWorker for this kind of thing. Take a look at Improve Application Performance With SwingWorker in Java SE 6.

like image 169
cletus Avatar answered Oct 04 '22 10:10

cletus


You should consider using SwingWorker since it will not block the UI thread, whereas both SwingUtilities methods will execute on the EDT thread, thus blocking the UI.

like image 27
Justin Ethier Avatar answered Oct 04 '22 12:10

Justin Ethier