swingworker--Tasks that Have Interim Results

Tasks that Have Interim Results

 

It is often useful for a background task to provide interim results while it is still working. The task can do this by invoking SwingWorker.publish. This method accepts a variable number of arguments. Each argument must be of the type specified by SwingWorker's second type parameter.

To collect results provided by publish, override SwingWorker.process This method will be invoked from the event dispatch thread. Results from multiple invocations of publish are often accumulated for a single invocation of process.

Let's look at the way the Flipper.java example uses publish to provide interim results. Click the Launch button to run Flipper using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

This program tests the fairness of java.util.Random by generating a series of random boolean values in a background task. This is equivalent to flipping a coin; hence the name Flipper. To report its results, the background task uses an object of type FlipPair

private static class FlipPair {

    private final long heads, total;

    FlipPair(long heads, long total) {

        this.heads = heads;

        this.total = total;

    }

}

The heads field is the number of times the random value has been true; the total field is the total number of random values.

The background task is represented by an instance of FlipTask:

private class FlipTask extends SwingWorker<Void, FlipPair> {

Since the task does not return a final result, it does not matter what the first type parameter is; Void is used as a placeholder. The task invokes publish after each "coin flip":

@Override

protected Void doInBackground() {

    long heads = 0;

    long total = 0;

    Random random = new Random();

    while (!isCancelled()) {

        total++;

        if (random.nextBoolean()) {

            heads++;

        }

        publish(new FlipPair(heads, total));

    }

    return null;

}

(The isCancelled method is discussed in the next section.) Because publish is invoked very frequently, a lot of FlipPair values will probably be accumulated before process is invoked in the event dispatch thread; process is only interested in the last value reported each time, using it to update the GUI:

protected void process(List<FlipPair> pairs) {

    FlipPair pair = pairs.get(pairs.size() - 1);

    headsText.setText(String.format("%d", pair.heads));

    totalText.setText(String.format("%d", pair.total));

    devText.setText(String.format("%.10g",

            ((double) pair.heads)/((double) pair.total) - 0.5));

}

 

 

public class Flipper extends JFrame

                  implements ActionListener {

    private final GridBagConstraints constraints;

    private final JTextField headsText, totalText, devText;

    private final Border border =

        BorderFactory.createLoweredBevelBorder();

    private final JButton startButton, stopButton;

    private FlipTask flipTask;

 

    private JTextField makeText() {

        JTextField t = new JTextField(20);

        t.setEditable(false);

        t.setHorizontalAlignment(JTextField.RIGHT);

        t.setBorder(border);

        getContentPane().add(t, constraints);

        return t;

    }

 

    private JButton makeButton(String caption) {

        JButton b = new JButton(caption);

        b.setActionCommand(caption);

        b.addActionListener(this);

        getContentPane().add(b, constraints);

        return b;

    }

    public Flipper() {

        super("Flipper");

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

 

        //Make text boxes

        getContentPane().setLayout(new GridBagLayout());

        constraints = new GridBagConstraints();

        constraints.insets = new Insets(3, 10, 3, 10);

        headsText = makeText();

        totalText = makeText();

        devText = makeText();

 

        //Make buttons

        startButton = makeButton("Start");

        stopButton = makeButton("Stop");

        stopButton.setEnabled(false);

 

        //Display the window.

        pack();

        setVisible(true);

    }

 

    private static class FlipPair {

        private final long heads, total;

        FlipPair(long heads, long total) {

            this.heads = heads;

            this.total = total;

        }

    }

 

    private class FlipTask extends SwingWorker<Void, FlipPair> {

        @Override

        protected Void doInBackground() {

            long heads = 0;

            long total = 0;

            Random random = new Random();

            while (!isCancelled()) {

                total++;

                if (random.nextBoolean()) {

                    heads++;

                }

                publish(new FlipPair(heads, total));

            }

            return null;

        }

 

        @Override

        protected void process(List<FlipPair> pairs) {

            FlipPair pair = pairs.get(pairs.size() - 1);

            headsText.setText(String.format("%d", pair.heads));

            totalText.setText(String.format("%d", pair.total));

            devText.setText(String.format("%.10g",

                    ((double) pair.heads)/((double) pair.total) - 0.5));

        }

    }

 

 

 

    public void actionPerformed(ActionEvent e) {

        if ("Start" == e.getActionCommand()) {

            startButton.setEnabled(false);

            stopButton.setEnabled(true);

            (flipTask = new FlipTask()).execute();

        } else if ("Stop" == e.getActionCommand()) {

            startButton.setEnabled(true);

            stopButton.setEnabled(false);

            flipTask.cancel(true);

            flipTask = null;

        }

 

    }

 

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {

                new Flipper();

            }

        });

    }

}

 

發佈了33 篇原創文章 · 獲贊 0 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章