SwingWorker In multithreaded Jframes

前端 未结 1 1028
忘掉有多难
忘掉有多难 2020-12-11 11:38

I am creating 4 threads and each thread is associated with a UI. The UI performs a long running task, for that I have used a SwingWorker. But the problem that arises is inst

相关标签:
1条回答
  • 2020-12-11 12:15

    Um, no, this is not how multithreading works in Swing.

    There is a single UI thread (known as the Event Dispatching Thread), all updates and interactions with the UI are expected to be done from within the context of the EDT, so doing things like...

    @Override
    public void run()
    {
        try
        {
            UI ui = new UI();
            ui.startThread();
        }
        catch(Exception ae)
        {
            ae.printStackTrace();
        }
    }
    

    And...

    @Override
    protected Integer doInBackground() throws Exception 
    {                
        for(int i=0; i<10;i++)
        {
            jTextArea1.append(""+i);
            Thread.sleep(3000);
        }
        return 0;
    }
    

    Are actually breaking this rule.

    Instead, each UI should have its own SwingWorker (as it does now), but should be created from within the context of the EDT.

    Each SwingWorker should be calling publish in order to push the results of the doInBackground method back to the EDT.

    SwingWorker has its own progress support via the PropertyChange support

    For example...

    import java.awt.BorderLayout;
    import java.awt.EventQueue;
    import java.awt.GridLayout;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import java.util.ArrayList;
    import java.util.List;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JProgressBar;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.SwingUtilities;
    import javax.swing.SwingWorker;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class MultiThreadedUI {
    
        public static void main(String[] args) {
            new MultiThreadedUI();
        }
    
        public MultiThreadedUI() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    final List<TestPane> panes = new ArrayList<>(5);
                    for (int index = 0; index < 5; index++) {
                        panes.add(new TestPane(Integer.toString(index)));
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new GridLayout(0, 1));
                    for (TestPane pane : panes) {
                        frame.add(pane);
                    }
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
    
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            for (TestPane pane : panes) {
                                pane.makeItSo();
                            }
                        }
                    });
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private JTextArea textArea;
            private JProgressBar pb;
            private String name;
    
            public TestPane(String name) {
                this.name = name;
                textArea = new JTextArea(10, 5);
                pb = new JProgressBar();
                setLayout(new BorderLayout());
                add(new JScrollPane(textArea));
                add(pb, BorderLayout.SOUTH);
            }
    
            public void makeItSo() {
    
                BackgroundWorker worker = new BackgroundWorker();
                worker.addPropertyChangeListener(new PropertyChangeListener() {
                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {
                        if ("progress".equalsIgnoreCase(evt.getPropertyName())) {
                            pb.setValue((Integer)evt.getNewValue());
                        }
                    }
                });
                worker.execute();
    
            }
    
            protected class BackgroundWorker extends SwingWorker<Integer, Integer> {
    
                @Override
                protected void process(List<Integer> chunks) {
                    for (Integer value : chunks) {
                        textArea.append(name + ": " + value + "\n");
                    }
                }
    
                @Override
                protected Integer doInBackground() throws Exception {
                    int delay = (int)(Math.random() * 3000);
                    for (int i = 0; i < 10; i++) {
                        publish(i);
                        setProgress((int) (Math.round(((double) i / (double) 9) * 100)));
                        Thread.sleep(delay);
                    }
                    return 0;
                }
    
            }
    
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题