How to asynchronous trigger JProgressBar?

為{幸葍}努か 提交于 2019-12-11 06:57:23

问题


I have a JButton(swing) in the JPanel, where if it is pressed I am performing a task on the for loop over the list in its EDT thread. While doing so I need to update the JProgressBar.

Problem is, when I am pressing the JButton the task is performed in Event Dispatch Thread (EDT). So I can't update the JProgressBar which is triggered either in main or UI thread.

Right now the source code is not available at me as I completely changed it and tried to use Eclipse SWT for JProgressBar when that Swing JButton is triggered, it becomes messy.

Now I got invalid thread access error, as the Display object runs in separate UI thread. At a time, only either a Swing JPanel or Eclipse SWT Shell gets displayed.

I am triggering JPanel using JOptionPane.


回答1:


You need to do your long running job and updating the progress bar value in a separate Thread from EDT. Most of the time SwingWorker is a good way to do that. So in your ActionListener of that button you should separate the long running thread from the EDT. You can do it with bare Thread but Workers and specially SwingWorker is designed for such cases:

package graphics;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class GraphicDev extends JFrame{

    private static final long serialVersionUID = 679207429168581441L;
    //
    private static final int FRAME_WIDTH = 300;
    private static final int FRAME_HEIGHT = 100;

    private int percent;
    private JProgressBar progress;

    public GraphicDev() {
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds(dim.width/2-FRAME_WIDTH/2, dim.height/2-FRAME_HEIGHT/2, FRAME_WIDTH, FRAME_HEIGHT);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //
        setLayout(new FlowLayout());
        //
        progress = new JProgressBar(0, 100);
        progress.setStringPainted(true);
        //
        JButton actButton = new JButton("Start!");
        actButton.addActionListener(new ActionListener() {          
            @Override
            public void actionPerformed(ActionEvent e) {
                new SwingWorker<Void, Void>() {
                    @Override
                    protected Void doInBackground() throws Exception {
                        for (long i = 0; i < 10000000000000L; i++) {
                            System.out.println(i);
                            if(i%200000 == 0){
                                progress.setValue(percent++);
                            }
                            if(percent >= 100){
                                break;
                            }
                        }
                        return null;
                    }

                    @Override
                    protected void done() {
                        JOptionPane.showMessageDialog(GraphicDev.this, "Done!");
                    }

                }.execute();    
            }
        });
        //
        add(actButton);
        add(progress);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                GraphicDev g = new GraphicDev();
                g.setVisible(true);
            }
        });
    }
}

Hope this would be helpful.




回答2:


Asynchronously handling JProgressBar progress using SwingWorker in detailed using two Swing JButton btnStart and btnStop.

and here we go for the source code-

package com.practice;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class ProgressExample {

    private static JFrame frame;
    private static JButton btnStart;
    private static JButton btnStop;
    private static JProgressBar progress;
    private static Integer currValue;
    private static boolean swingWorkerHelper;
    private static SwingWorker<Integer, Void> swingWorker;

    public static void main(String[] args) {
        // Scheduling Swing app for the event dispatch thread(EDT) Asynchronously
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                runSwingAsynchronousApp();
            }
        });
    }

    private static void runSwingAsynchronousApp() {
        currValue = new Integer(0);

        btnStart = new JButton("Start");
        btnStop = new JButton("Stop");

        progress = new JProgressBar();
        progress.setMinimum(0);
        progress.setMaximum(100);
        progress.setStringPainted(true);

        btnStart.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {

                if (btnStart.getText().equals("Pause")) {
                    // interrupting swingWorker method doInBackground() implicitly safely.
                    swingWorkerHelper = false;
                    btnStart.setText("Resume");
                } else {
                    if (btnStart.getText().equals("Start") || btnStart.getText().equals("Resume"))
                        btnStart.setText("Pause");

                    showProgress();
                }
            }
        });

        btnStop.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {
                // checking swingWorker Object is initialized or not
                if (swingWorker != null) {
                    // checking is swingWorker doing process in background or not
                    if (swingWorker.getState() == SwingWorker.StateValue.STARTED) {
                        btnStart.setText("Start");
                        // interrupting swingWorker method doInBackground() explicitly
                        swingWorker.cancel(true);
                        currValue = new Integer(0);
                    }
                }
            }
        });

        frame = new JFrame();
        frame.setTitle("Asynchronously trigger JProgressBar");
        frame.getContentPane().setLayout(new GridLayout(3, 2));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(400, 250, 400, 300);

        frame.getContentPane().add(btnStart);
        frame.getContentPane().add(btnStop);
        frame.getContentPane().add(progress);

        frame.setVisible(true);
    }

    private static void showProgress() {
        swingWorker = new SwingWorker<Integer, Void>() {
            @Override
            protected Integer doInBackground() throws Exception {

                if (!swingWorkerHelper)
                    swingWorkerHelper = true;

                while (currValue < progress.getMaximum() && swingWorkerHelper) {
                    try {
                        progress.setValue(++currValue);

                        if (isCancelled())
                            return currValue;

                        Thread.sleep(70);
                    } catch (InterruptedException iex) {
                        swingWorkerHelper = false;
                        System.out.println("Stop Button interrupted SwingWorker process...");
                    }
                }
                return currValue;
            }

            @Override
            public void done() {
                System.out.printf("Progress ends with value %s " + 
                (isCancelled() ? "with" : "without") + " interruption.\n", currValue);
                if (currValue >= progress.getMaximum()) {
                    btnStart.setText("Start");
                    currValue = new Integer(0);
                }
            }
        };
        swingWorker.execute();
    }

}

Hope this would help you.



来源:https://stackoverflow.com/questions/48144967/how-to-asynchronous-trigger-jprogressbar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!