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

前端 未结 1 436
盖世英雄少女心
盖世英雄少女心 2020-12-12 06:08

I am using SwingWorker class to make a process run in another thread. What I want is, once this thread has finished processing, it should return a String<

相关标签:
1条回答
  • 2020-12-12 06:33

    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

    0 讨论(0)
提交回复
热议问题