有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何异步触发JProgressBar?

我在JPanel中有一个JButtonswing),如果它被按下,我在其EDT thread列表上的for循环上执行任务。在这样做的同时,我需要更新JProgressBar

问题是,当我按下JButton时,任务是在事件调度线程(EDT)中执行的。因此,我无法更新在主线程或UI线程中触发的JProgressBar

现在,源代码对我来说是不可用的,因为我完全更改了它,并尝试将Eclipse SWT用于JProgressBar。当Swing JButton被触发时,它会变得混乱

现在我得到了invalid thread access错误,因为Display对象在单独的UI线程中运行。一次只能显示SwingJPanel或Eclipse SWTShell

我正在使用JOptionPane触发JPanel


共 (2) 个答案

  1. # 1 楼答案

    您需要在独立于EDT的线程中执行长时间运行的工作并更新进度条值。大多数时候SwingWorker是一个很好的方法。因此,在该按钮的ActionListener中,应该将长时间运行的线程与EDT分开。你可以用裸Thread来做,但是工人和特别的SwingWorker是为这种情况设计的:

    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);
                }
            });
        }
    }
    

    希望这会有帮助

  2. # 2 楼答案

    Asynchronously使用SwingWorker处理JProgressBar进度,详细使用两个Swing JButton btnStart and btnStop

    enter image description here

    我们来看看源代码-

    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();
        }
    
    }
    

    希望这对你有帮助