我有以下代码:

try {
    SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
        try {
            dialog.handleDownload();
        } catch (IOException io) {
            io.printStackTrace();
            }
        }
    });
} catch(Exception io) { io.printStackTrace(); }


handleDownload中,我正在读取输入流,计算进度条的值,并将其设置为该值。因此,当我单击一个按钮时,将打开一个新的JFrame并执行我在上面编写的所有内容。

如果我自己有dialog.handleDownload(在没有SwingUtilities方法中),它将冻结直到操作完成。如果将其添加到invokeLater中,则会非常快速地关闭(我什么也看不到,并且操作未完成)。如果将其添加到invokeAndWait中,则无法从事件分配器线程错误中调用invokeAndWait。我该怎么办?

最佳答案

看来您可以使用SwingWorker。这使您可以将昂贵的操作推迟到后台线程(保持GUI响应),并且在操作完成后,对GUI进行一些处理。

编辑:示例

这是一个更复杂的示例,显示了如何使用SwingWorker的基础知识,以及如何发布/处理中间结果。

public static void main(String[] args) {
    final int SIZE = 1024*1024; //1 MiB

    //simulates downloading a 1 MiB file
    final InputStream in = new InputStream() {
        int read = 0;
        public int read() throws IOException {
            if ( read == SIZE ) {
                return -1;
            } else {
                if ( read % 200 == 0 ) {
                    try { Thread.sleep(1); } catch ( InterruptedException e ) {}
                }
                read++;
                return 5;
            }
        }
    };

    final JProgressBar progress = new JProgressBar(0, SIZE);

    final JButton button = new JButton("Start");
    button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            button.setText("Working...");
            SwingWorker<byte[], Integer> worker = new SwingWorker<byte[], Integer>() {
                @Override
                protected byte[] doInBackground() throws Exception {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    byte[] buff = new byte[1024];
                    for ( int read = -1; (read = in.read(buff)) != -1; ) {
                        baos.write(buff, 0, read);
                        publish(read);
                    }
                    return baos.toByteArray();
                }

                @Override
                protected void process(List<Integer> chunks) {
                    int total = 0;
                    for ( Integer amtRead : chunks ) {
                        total += amtRead;
                    }
                    progress.setValue(progress.getValue() + total);
                }

                @Override
                protected void done() {
                    try {
                        byte[] data = get();
                        button.setText("Read " + data.length + " bytes");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
            worker.execute();
        }
    });

    JFrame frame = new JFrame();
    frame.setLayout(new BorderLayout());
    frame.add(button, BorderLayout.NORTH);
    frame.add(progress, BorderLayout.SOUTH);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack(); frame.setVisible(true);
}


编辑:更改示例以驱动进度条,就像正在进行下载一样。

09-30 17:38