Search code examples
javaswingswingworker

SwingWorker setting a flag after finishing its work


I have put together an application that opens text files and allows users to edit them (eg: text editor)

Some text files can be arbitrarily large, so it would take some time to open them. I have added a progress bar to inform the user that stuff is actually happening, and am using a swing worker to perform the actual file loading, giving it a reference to a text area to dump all the text.

I also have a flag in the main application called isFileLoaded which is true if there's a file open, and false otherwise. Ideally, the swing worker should set that value after it finishes loading the file and doing any processing that it needs to do.

I have written the swing worker as a separate class, so it's not nested inside my main Frame class that holds all of the GUI logic, mainly because I do not like to define classes inside classes purely for aesthetic reasons. As such, I am currently passing a reference to the entire Frame to the swing worker and letting it set the value of the flag.

Is this a good way to do things? Are there better ways?


Solution

  • Consider rather adding a PropertyChangeListener which holds a reference to your Frame (an anonymous inner-class would be just fine for that matter) and which listens to the "state" property. The value of the event will be equal to StateValue.DONE when the SwingWorker has finished.

    Here is a fully working example:

    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import java.util.List;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JProgressBar;
    import javax.swing.SwingUtilities;
    import javax.swing.SwingWorker;
    import javax.swing.SwingWorker.StateValue;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class TestSwingWorker {
    
        private JProgressBar progressBar;
    
        protected void initUI() {
            final JFrame frame = new JFrame();
            frame.setTitle(TestSwingWorker.class.getSimpleName());
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JButton button = new JButton("Clik me to start work");
            button.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    doWork();
                }
            });
            progressBar = new JProgressBar(0, 100);
            frame.add(progressBar, BorderLayout.NORTH);
            frame.add(button, BorderLayout.SOUTH);
            frame.pack();
            frame.setVisible(true);
        }
    
        private boolean someFlag;
    
        protected void doWork() {
            SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
                @Override
                protected Void doInBackground() throws Exception {
                    for (int i = 0; i < 100; i++) {
                        // Simulates work
                        Thread.sleep(10);
                        publish(i);
                    }
                    return null;
                }
    
                @Override
                protected void process(List<Integer> chunks) {
                    progressBar.setValue(chunks.get(chunks.size() - 1));
                }
    
                @Override
                protected void done() {
                    progressBar.setValue(100);
                    progressBar.setStringPainted(true);
                    progressBar.setString("Done");
                }
            };
            worker.getPropertyChangeSupport().addPropertyChangeListener("state", new PropertyChangeListener() {
    
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if (StateValue.DONE.equals(evt.getNewValue())) {
                        someFlag = true;
                    }
                }
            });
            worker.execute();
        }
    
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
                UnsupportedLookAndFeelException {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new TestSwingWorker().initUI();
                }
            });
        }
    }