java - JProgressBar 不会更新

标签 java swing concurrency event-dispatch-thread jprogressbar

我正在尝试将 JProgressBar 添加到我的程序中,但它不会更新!该值仅在推理 100% 后才会更改。这是我的方法。

public void downloadImages(List<String> images) {
    if (errorCode == 0) {
        for (int i = 0; i < images.size(); i++) {
            if (errorCode == 0) {
                main.progressLabel.setText("Downloading image " + Integer.toString(i + 1) + " of " + Integer.toString(images.size()));
                String imageStr = images.get(i);
                String imageName = imageStr.substring(imageStr.lastIndexOf("/") + 1);
                try {
                    URL url = new URL(imageStr);
                    InputStream in = url.openStream();
                    OutputStream out = new FileOutputStream(saveDirectory + imageName);

                    byte[] b = new byte[2048];
                    int length;
                    while ((length = in.read(b)) != -1) {
                        out.write(b, 0, length);
                    }

                    in.close();
                    out.close();
                } catch (MalformedURLException e) {
                    errorCode = BAD_URL;
                } catch (IOException e) {
                    errorCode = INVALID_PATH;
                }
                main.progressBar.setValue(((i+1)/images.size())*100);
            }

        }
    }
}

更改进度条值位于上述方法的底部。

这是我调用该方法的方式。

public void download() {
    final Downloader downloader = new Downloader(this, albumUrl.getText(), downloadPath.getText());
    progressBar.setValue(0);
    downloadButton.setEnabled(false);

    new Thread(new Runnable() {
        public void run() {
            List<String> images = downloader.getImages(downloader.getPageSource());
            downloader.downloadImages(images);
            if (downloader.getErrorCode() == 0) {
                progressLabel.setText("All images have been downloaded!");
            } else {
                String error = "";
                switch (downloader.getErrorCode()) {
                case Downloader.BAD_URL:
                case Downloader.NOT_IMGUR_ALBUM:
                    error = "The URL entered is either invalid or does not link to an Imgur album.";
                    break;
                case Downloader.BLANK_URL:
                    error = "The album URL field cannot be blank.";
                    break;
                case Downloader.INVALID_PATH:
                    error = "The system cannot find the download directory path specified.";
                    break;
                case Downloader.BLANK_PATH:
                    error = "The download directory cannot be blank.";
                    break;
                case Downloader.CANNOT_READ_URL:
                    error = "An error occoured while reading the URL.";
                    break;
                case Downloader.PARSING_ERROR:
                    error = "An error occoured while parsing the URL.";
                    break;
                }
                JOptionPane.showMessageDialog(Main.this, error, "Error", 0);
            }
            downloadButton.setEnabled(true);
        }
    }).start();
}

编辑:上面根本不是问题,问题是程序使用整数除法而不是小数。

最佳答案

主要问题是,您阻止了 Event Dispatch Thread ,通过在 GUI EDT 上执行长时间运行的任务。

而是使用SwingWorker .

这是一个小例子:

enter image description here

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;

public class ProgressBarDemo extends JPanel {

    private JButton startButton;
    private JTextArea taskOutput;

    public ProgressBarDemo() {
        super(new BorderLayout());

        final JProgressBar progressBar = new JProgressBar(0, 100);
        progressBar.setValue(0);
        progressBar.setStringPainted(true);

        taskOutput = new JTextArea(5, 20);
        taskOutput.setMargin(new Insets(5, 5, 5, 5));
        taskOutput.setEditable(false);

        // Create the demo's UI.
        startButton = new JButton("Start");
        startButton.setActionCommand("start");
        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                startButton.setEnabled(false);
                setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                // Instances of javax.swing.SwingWorker are not reusuable, so
                // we create new instances as needed.
                final Task task = new Task();
                task.addPropertyChangeListener(new PropertyChangeListener() {
                    @Override
                    public void propertyChange(PropertyChangeEvent pce) {
                        if ("progress".equals(pce.getPropertyName())) {
                            int progress = (Integer) pce.getNewValue();
                            progressBar.setValue(progress);
                            taskOutput.append(String.format("Completed %d%% of task.\n", task.getProgress()));
                        }
                    }
                });
                task.execute();
            }
        });

        JPanel panel = new JPanel();
        panel.add(startButton);
        panel.add(progressBar);

        add(panel, BorderLayout.PAGE_START);
        add(new JScrollPane(taskOutput), BorderLayout.CENTER);
        setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

    }

    /**
     * Create the GUI and show it. As with all GUI code, this must run on the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        JFrame frame = new JFrame("ProgressBarDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel progressBarPanel = new ProgressBarDemo();
        frame.add(progressBarPanel);

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        // Schedule a job for the event-dispatching thread:
        // creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private class Task extends SwingWorker<Void, Void> {

        /*
         * Main task. Executed in background thread.
         */
        @Override
        public Void doInBackground() {
            Random random = new Random();
            int progress = 0;
            // Initialize progress property.
            setProgress(0);
            while (progress < 100) {
                // Sleep for up to one second.
                try {
                    Thread.sleep(random.nextInt(1000)-15);
                } catch (InterruptedException ignore) {
                }
                // Make random progress.
                progress += random.nextInt(10);
                setProgress(Math.min(progress, 100));
            }
            return null;
        }

        /*
         * Executed in event dispatching thread
         */
        @Override
        public void done() {
            Toolkit.getDefaultToolkit().beep();
            startButton.setEnabled(true);
            setCursor(null); // turn off the wait cursor
            taskOutput.append("Done!\n");
        }
    }
}

关于java - JProgressBar 不会更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14271902/

相关文章:

java - 如何更新预定的 quartz 作业?

java - 文件夹目的地 - 上传文件

java - JFileChooser 查询

java - 全屏上的 Swing 布局边框边距

java - 线程意外操纵的变量

Java传递字符串数组

java - 类中的泛型和方法数量

java - Netbeans JAR 未正常运行/打开

sql - 涉及 SELECT FOR UPDATE 的死锁

loops - 是否可以从外部功能停止股票行情/股票报价?