1

The following MCVE demonstrates a Swing gui running a long process. The long process runs within a SwingWorker so it does not block (freeze) the GUI:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingWorker;

public class DiagA extends JDialog  {

    private FrameB frame;
    private JButton btn;

    public  DiagA() {

        super();
        setTitle("main frame");
        setSize(200, 150);
        setLocation(400,400);

        btn = new JButton("Show Frame B");
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {

                show2ndFrame();
            }
        });
        add(btn, BorderLayout.NORTH);
        setVisible(true);
    }

    void show2ndFrame() {

        if(frame == null) {

            frame = new FrameB();
            btn.setText("Exit");

        }else {

            System.exit(0);
        }

        doWork();
    }

    private void doWork() {

        SwingWorker<Void, Void> sw = new SwingWorker<Void, Void>() {

            @Override
            protected Void doInBackground() throws Exception {

                try {

                    for(int i = 1 ; i<=100 ; i++) {
                        //represents a long process
                        Thread.sleep(100);
                        frame.update(i);
                    }

                } catch (InterruptedException ex) {}
                return null;
            }
        };
        sw.execute();
    }

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

class FrameB extends JFrame  {

   JLabel label;

    public  FrameB() {

        super();
        setTitle("2nd frame");
        setSize(150, 100);
        setLocation(600,420);
        setLayout(new FlowLayout(FlowLayout.CENTER));
        getContentPane().setBackground(Color.YELLOW);
        label = new JLabel("0");
        add(label);
        setVisible(true);
    }

    void update(int progress) {

        label.setText(String.valueOf(progress));
    }
}


Assuming that FrameB needs to be updated by several different long processes, I find it quiet cumbersome to run each such process within a SwingWorker.
Is there an alternative approach ?

c0der
  • 18,467
  • 6
  • 33
  • 65
  • 2
    Run each process in a `Thread`, but just make sure any GUI updates are scheduled using `invokeLater(..)`. Mind you, `SwingWorker` was intended as the API to make `Thread`/`invokeLater(..)` less cumbersome! – Andrew Thompson Sep 16 '16 at 05:58
  • 3
    Keep in mind that `doInBackground` is executed in the worker thread and not the UI thread (Event Dispatcher Thread). So you should not invoke `frame.update()` in that method. The worker thread should use the `publish` method and you should override `process` to update ui components. – René Link Sep 16 '16 at 07:48
  • @RenéLink Thanks for your comment. In real programs I use `publish` , `process` or `get` (if I only need final return value). I tried to keep the MCVE as M as possible. – c0der Sep 16 '16 at 12:30
  • 1
    Can you elaborate on what you mean by _cumbersome_? You can manage multiple workers like [this](http://stackoverflow.com/a/11372932/230513). – trashgod Sep 16 '16 at 13:17

0 Answers0