GUI and EDT management in a multitask application

I developed a Java application for creating and extracting an archive - for example WinRAR . You can create multiple archives at the same time using multithreading. And recently, I wanted to add the status of the information during the creation of the archive as a JProgressBar in the new JFrame with each creation.

But my problem is to generate information in a new state frame and the stream that the archive creates. Therefore, I create a JFrame in the archive stream to update the current progress bar.

But, as I could read it in a varied source of information and your answers / comments, it is against Java Swing and performance; I cannot create a swing object elsewhere that EDT .

But then, how should I solve my problem? How can I establish a connection between the writing of my archive and its JFrame status (with JProgressBar)?


EDIT:

I used SwingWorker to control the GUI in my application. Now everything, I have another question:

With SwingWorker, how do I work on a background task with an event on the status of a Frame button? (Example: pause compression or stop it.)

+3
source share
3 answers

As suggested by others, the best way is to use SwingWorker .

SwingWorker properties are obeyed, and listeners always invoke in EDT, so you can do something like:

 public class ArchivingWorker extends SwingWorker<Void, Void> { JProgressBar progressBar = null; // Other members here... ... public ArchivingWorker(...) { // Any specific initialization here (in EDT) addPropertyChangeListener(new PropertyChangeListener() { @Override void propertyChange(PropertyChangeEvent e) { if ( "state".equals(e.getPropertyName()) && e.getNewValue() == StateValue.STARTED) { // Background thread has just started, show a progress dialog here progressBar = new JProgressBar(); ... } else if ("progress".equals(e.getPropertyName())) { // Update progress bar here with e.getNewValue() ... } } }); } @Override protected Void doInBackground() { // Archiving process here and update progress from time to time setProgress(progress); return null; } @Override protected void done() { // Ensure that archiving process worked correctly (no exception) try { get(); } catch (Exception e) { // Handle exception (user feedback or whatever) } finally { // Close progress dialog ... } } } 

Then you can use ArchivingWorker as needed:

 ArchivngWorker worker = new ArchivingWorker(...); worker.execute(); 
+5
source
  • Place and show JProgressBar in JDialog , and do not create a new top-level container . Create it once and reuse it

  • Long-term and heavy code will be better redirected to the BackGround task

  • You can move with JProgressBar step from background task

    • only if GUI related code is executing on EDT more than Concurrency in Swing

    • and there are two right ways to do it

      • using SwingWorker

      • from Runnable#Thread , but GUI code must be wrapped in invokeLater()

+5
source

The answer provided by @mKorbel is fine, but there really is no need to use another top-level container (like JDialog ) to display the progress bar. Instead, you can use the glass panel of the JFrame instance.

+1
source

All Articles