How to use the Swing Timer to delay the loading of

2019-01-20 16:42发布

I need to find a way to use the Swing Timer with a progress bar. I tried using Thread.sleep(), but it crashed the app when I used it. Any ways to use the Swing Timer instead of the Sleep()?

public void piiEros(int dist)
{
    Pii pii = new Pii();
    pii.setVisible(true);
    for(int pc = 0;100 > pc; pc++)
    {
        try {
            Thread.sleep(dist/100);
        } catch (InterruptedException ex) {
            Logger.getLogger(Trav.class.getName()).log(Level.SEVERE, null, ex);
        }
        pii.pg.setValue(pc);
    }
    pii.dispose();
    o.Eros();
}

NOTES: Pii is a class with th Progress Bar. Dist is the speed at which it loads. Trav is the class the method is in. Pc stands for %, how much is done is displyed on the bar. o.Eros opens anotherr GUI.

2条回答
ゆ 、 Hurt°
2楼-- · 2019-01-20 17:21

It's probably easier (in the long run) to use a SwingWorker. It supplies a number of useful methods for updating the UI (from the context of the Event Dispatching Thread) while allowing to continue executing in the background...

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestSwingWorker02 {

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

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

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

        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            JProgressBar pb = new JProgressBar();
            add(pb);

            new ProgressWorker(pb, 40).execute();
        }

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

    }

    public class ProgressWorker extends SwingWorker<Void, Integer> {

        private int delay;
        private JProgressBar pb;

        public ProgressWorker(JProgressBar progressBar, int delay) {
            this.pb = progressBar;
            this.delay = delay;
        }

        @Override
        protected void process(List<Integer> chunks) {
            // Back in the EDT...
            pb.setValue(chunks.get(chunks.size() - 1)); // only care about the last one...
        }

        @Override
        protected Void doInBackground() throws Exception {
            for (int index = 0; index < 100; index++) {
                publish(index);
                Thread.sleep(delay);
            }
            return null;
        }

        @Override
        protected void done() {
            // Back in the EDT...
            //pii.dispose();
            //o.Eros();
        }

    }

}

The SwingWorker allows you to separate the logic. In the doInBackground method you can focus on that part of the code that needs to operate outside the EDT, you can publish updates back to the EDT and process them separately. When it's all done you can clean up as required.

SwingWorker also provides a progress monitoring functionality, so, in your case, this would you wouldn't have to use the publish/process portion of the API if you didn't want to. This would allow you to attach a PropertyChangeListener to a the worker without the need to expose the progress bar to it. (But I did for the example)

public class ProgressWorker extends SwingWorker<Void, Integer> {

    private int delay;
    private JProgressBar pb;

    public ProgressWorker(JProgressBar progressBar, int delay) {
        this.pb = progressBar;
        this.delay = delay;
        // You can use a property change listener to monitor progress updates...
        addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if ("progress".equalsIgnoreCase(evt.getPropertyName())) {
                    pb.setValue((Integer)evt.getNewValue());
                }
            }

        });
    }

    @Override
    protected Void doInBackground() throws Exception {
        for (int index = 0; index < 100; index++) {
            setProgress(index);
            Thread.sleep(delay);
        }
        return null;
    }

    @Override
    protected void done() {
        // Back in the EDT...
        //pii.dispose();
        //o.Eros();
    }

}
查看更多
何必那么认真
3楼-- · 2019-01-20 17:34

you can change your piiEros method in this way:

public void piiEros(int dist)
{
    final Pii pii = new Pii();
    pii.setVisible(true);
    javax.swing.Timer  timer = new javax.swing.Timer(dist/100, new ActionListener()
    {
      public void actionPerformed(ActionEvent evt)
      {
        pii.pg.setValue(pg.getValue()++);
        if ( pii.pg.getValue() > 100 )
        {
          timer.stop();
          pii.dispose();
          o.Eros();
        }
      }
    });
    timer.setInitialDelay(0);
    timer.setRepeats(true);
    timer.start();
}
查看更多
登录 后发表回答