Manage GUI and EDT in a multi-task application

前端 未结 3 1432
终归单人心
终归单人心 2021-01-20 21:44

I developed a Java application for creating and extracting an archive - like WinRAR. You can create several archives at the same time with multithreading. And recently, I wa

相关标签:
3条回答
  • 2021-01-20 22:18

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

    0 讨论(0)
  • 2021-01-20 22:23
    1. Put and display JProgressBar in a JDialog, and don't create a new Top-Level Container. Create that once and re-use that

    2. Long timed and heavy code would be better redirected to the BackGround Task

    3. You can move with progress in JProgressBar from a background task

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

      • and there are two correct ways to do it

        • by using SwingWorker

        • from Runnable#Thread but GUI rellated code must be wrapped into invokeLater()

    0 讨论(0)
  • 2021-01-20 22:31

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

    SwingWorker properties are listenable and listeners are always called in the EDT, thus, you could 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 you need it:

    ArchivngWorker worker = new ArchivingWorker(...);
    worker.execute();
    
    0 讨论(0)
提交回复
热议问题