How to return value from SwingWorker class and use in other class and enable MenuItem when process is done?

五迷三道 提交于 2019-11-28 14:42:55

Since you're using a JDialog to manage the SwingWorker, you can actual use the modal state of the dialog to you advantage.

Essentially, when a dialog is modal, it will block the code execution where the dialog is made visible. It will block until the dialog is hidden, at which time, the code will continue to execute.

So, you can disable the button before the dialog is made visible and re-enable it when it's closed.

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            JButton btn = new JButton("Go");
            add(btn);

            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    btn.setEnabled(false);
                    SomeWorkerDialog worker = new SomeWorkerDialog(TestPane.this);
                    // This is just so we can see the button ;)
                    Point point = btn.getLocationOnScreen();
                    worker.setLocation(worker.getX(), point.y + btn.getHeight());
                    worker.setVisible(true);
                    btn.setEnabled(true);
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public class SomeWorkerDialog extends JDialog {

        private JProgressBar progressBar;
        private SomeWorkerSomeWhere worker;


        public SomeWorkerDialog(JComponent parent) {
            super(SwingUtilities.getWindowAncestor(parent), "Working Hard", DEFAULT_MODALITY_TYPE);

            progressBar = new JProgressBar();
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.HORIZONTAL;
            gbc.weightx = 1;
            gbc.insets = new Insets(10, 10, 10, 10);

            add(progressBar, gbc);

            worker = new SomeWorkerSomeWhere();
            worker.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    String name = evt.getPropertyName();
                    switch (name) {
                        case "state":
                            switch (worker.getState()) {
                                case DONE:
                                    setVisible(false);
                                    break;
                            }
                            break;
                        case "progress":
                            progressBar.setValue(worker.getProgress());
                            break;
                    }
                }
            });

            addWindowListener(new WindowAdapter() {

                @Override
                public void windowOpened(WindowEvent e) {
                    worker.execute();
                }

                @Override
                public void windowClosed(WindowEvent e) {
                    worker.cancel(true);
                }

            });

            pack();
            setLocationRelativeTo(parent);

        }

    }

    public class SomeWorkerSomeWhere extends SwingWorker {

        @Override
        protected Object doInBackground() throws Exception {
            for (int index = 0; index < 100 && !isCancelled(); index++) {
                setProgress(index);
                Thread.sleep(10);
            }
            return "AllDone";
        }

    }

}

Update

To get the value returned by the worked, you can add a method to the dialog which returns the calculated value...

public String getValue() throws Exception {
    return worker.get()
}

So, once the dialog is closed and the execution of your code continues, you can enable the components you want and call the getValue method

You can also store the result when the state changes and the PropertyChangeListener is notified

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!