JProgressBar不会更新
我正在尝试从这个问题的投票答案我发现的代码: 下载文件使用Java的Apache公共?
这是一个下载应用程序,看看,(我不熟悉JFrames和ActionEvents)
Download.java
package main; public class Download extends JFrame implements Runnable{ public static int total; public static int done; private static class ProgressListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { done = (int)((DownloadCountingOutputStream) e.getSource()).getByteCount(); jbar.repaint(); DownloadCountingOutputStream.parent.draw((int)((DownloadCountingOutputStream) e.getSource()).getByteCount());//redraw DownloadCountingOutputStream.parent.repaint(); } } public static JProgressBar jbar = new JProgressBar(); public void draw(int downloaded){System.out.println("downloaded: "+downloaded+ " Total: "+total); if (downloaded== 0){ Container cont = new Container(); setDefaultCloseOperation(3); setSize(600, 450); setResizable(false); setVisible(true); cont.add(jbar); jbar.setBounds(40, 50, 500, 50); jbar.setMaximum(total);//The total value of bytes to download //jbar.setValue(50); add(cont); jbar.setVisible(true); } jbar.setValue(downloaded); //This should update the value of the progress Bar } public void run() { URL dl = null; File fl = null; OutputStream os = null; InputStream is = null; ProgressListener progressListener = new ProgressListener(); draw(done); try { fl = new File(System.getProperty("user.home").replace("\\", "/") + "/Desktop/afile.rar"); dl = new URL("https://dl.dropbox.com/u/48076798/afile.rar"); os = new FileOutputStream(fl); is = dl.openStream(); total = Integer.parseInt(dl.openConnection().getHeaderField("Content-Length")); String total = dl.openConnection().getHeaderField("Content-Length"); DownloadCountingOutputStream dcount = new DownloadCountingOutputStream(os); dcount.setListener(progressListener); dcount.setParent(this); IOUtils.copy(is, dcount); } catch (Exception e) { System.out.println(e); } finally { if (os != null) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
DownloadCountingOutputStream.java
package main; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.io.OutputStream; import org.apache.commons.io.output.CountingOutputStream; public class DownloadCountingOutputStream extends CountingOutputStream { private ActionListener listener = null; public static Download parent; public DownloadCountingOutputStream(OutputStream out) { super(out); } public void setListener(ActionListener listener) { this.listener = listener; } public void setParent(Download o){ parent = o; } @Override protected void afterWrite(int n) throws IOException { super.afterWrite(n); if (listener != null) { listener.actionPerformed(new ActionEvent(this, 0, null)); } } }
从您提供的代码示例中很难看出…
这个问题的主要原因是尝试更新UI,同时阻塞事件分派线程(EDT)。
在EDT中永远不要做长时间的运行或阻塞操作,这是很重要的,因为这将防止重新绘制请求被执行。
有关更多信息,请参阅Swing中的并发读取
下面的示例演示了如何使用SwingWorker
来提供与UI重新同步的进度更新
public class TestProgress { public static void main(String[] args) { new TestProgress(); } public TestProgress() { 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) { } ProgressPane progressPane = new ProgressPane(); JFrame frame = new JFrame("Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(progressPane); frame.setSize(200, 200); frame.setLocationRelativeTo(null); frame.setVisible(true); progressPane.doWork(); } }); } public class ProgressPane extends JPanel { private JProgressBar progressBar; public ProgressPane() { setLayout(new GridBagLayout()); progressBar = new JProgressBar(); add(progressBar); } public void doWork() { Worker worker = new Worker(); worker.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { progressBar.setValue((Integer) evt.getNewValue()); } } }); worker.execute(); } } public class Worker extends SwingWorker<Object, Object> { @Override protected Object doInBackground() throws Exception { for (int index = 0; index < 1000; index++) { int progress = Math.round(((float) index / 1000f) * 100f); setProgress(progress); Thread.sleep(10); } return null; } } }