更新两个JProgressBars

时间:2012-07-24 00:46:39

标签: java multithreading swing swingworker jprogressbar

所以,我使用了一个JProgressBar。如何更新两个单独的进度条?我正在doInBackground()工作线程/ swingworker方法中执行下载。我想更新两个吧,第一个是总数,第二个是总数的一部分。例如,总共21/100 // 21/50 / halvsies

我已经问了一个问题here,最后弄清楚了这个线程。我现在正在考虑提高赌注,并获得两个进度表。谢谢阅读, 凯特〜

4 个答案:

答案 0 :(得分:2)

您可以在更新“部分”进度时通过触发新的属性更改事件来利用属性更改支持。

根据您提供的信息,您可以通过多种方式实现这一目标。

您可以使用

之类的东西直接调用它
firePropertyChange("sectionProgress", oldProgress, newProgress);

现在显然,您遇到了可怕的ETD同步问题,因为firePropertyChange方法不是线程安全的。

但您可以创建一个简单的Updater类,在Runnable

中实现SwingWorker
private class TwoWorker extends SwingWorker<Double, Double> {

    protected Double doInBackGround() throws Exception {

        //... Do some work

        SwingUtilities.invokeLater(new Updater(oldProgress, newProgress));

    }

    public class Updater implements Runnable {

        private int oldProgress;
        private int newProgress;

        public Updater(int oldProgress, int newProgress) {
            this.oldProgress = oldProgress;
            this.newProgress = newProgress;
        }

        public void run() {
            firePropertyChange("sectionProgress", oldProgress, newProgress);
        }   

    }

}

答案 1 :(得分:2)

您可以利用SwingWorker<T,V>类型参数V,该参数用于在publishprocess方法中执行中间结果。例如:

class DownloadProgress {
    private int totalProgress;
    private int currentTaskProgress;

    public DownloadProgress(int totalProgress, int currentTaskProgress) {
        this.totalProgress = totalProgress;
        this.currentTaskProgress = currentTaskProgress;
    }
}

public class DownloadWorker extends SwingWorker<Double, DownloadProgress> {

    @Override
    protected Double doInBackground() throws Exception {
        ...
        publish(new DownloadProgress(1, 50));
    }

    @Override
    protected void process(List<DownloadProgress> progressList) {
        for (DownloadProgress p : progressList){
            //update progress bars
        }
    }
}

答案 2 :(得分:2)

这是一个简单的例子(@Max已经说过):

enter image description here

import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.Random;
import javax.swing.*;
public class TwoProgressBarsTest {
  private final JTextArea area     = new JTextArea();
  private final JPanel statusPanel = new JPanel(new BorderLayout(0,2));
  private final JButton runButton  = new JButton(new RunAction());
  private SwingWorker<String, DownloadProgress> worker;
  public JComponent makeUI() {
    area.setEditable(false);
    JPanel p = new JPanel(new BorderLayout(5,5));
    p.add(new JScrollPane(area));
    p.add(runButton, BorderLayout.NORTH);
    p.add(statusPanel, BorderLayout.SOUTH);
    p.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    return p;
  }
  class RunAction extends AbstractAction {
    public RunAction() {
      super("run");
    }
    @Override public void actionPerformed(ActionEvent evt) {
      final JProgressBar bar1 = new JProgressBar();
      final JProgressBar bar2 = new JProgressBar();
      runButton.setEnabled(false);
      statusPanel.add(bar1, BorderLayout.NORTH);
      statusPanel.add(bar2, BorderLayout.SOUTH);
      statusPanel.revalidate();
      worker = new SwingWorker<String, DownloadProgress>() {
        @Override public String doInBackground() {
          int current = 0;
          int lengthOfTask = 12; //filelist.size();
          publish(new DownloadProgress(Target.LOG, "Length Of Task: "+lengthOfTask));
          publish(new DownloadProgress(Target.LOG, "\n-------------------------\n"));
          while(current<lengthOfTask && !isCancelled()) {
            if(!bar1.isDisplayable()) {
              return "Disposed";
            }
            try {
              convertFileToSomething();
            } catch(InterruptedException ie) {
              return "Interrupted";
            }
            publish(new DownloadProgress(Target.LOG, "*"));
            publish(new DownloadProgress(Target.TOTAL, 100*current/lengthOfTask));
            current++;
          }
          publish(new DownloadProgress(Target.LOG, "\n"));
          return "Done";
        }
        private final Random r = new Random();
        private void convertFileToSomething() throws InterruptedException {
          int current = 0;
          //long lengthOfTask = file.length();
          int lengthOfTask = 10+r.nextInt(50);
          while(current<=lengthOfTask && !isCancelled()) {
            int iv = 100 * current / lengthOfTask;
            Thread.sleep(20); // dummy
            publish(new DownloadProgress(Target.FILE, iv+1));
            current++;
          }
        }
        @Override protected void process(List<DownloadProgress> chunks) {
          for(DownloadProgress s: chunks) {
            switch(s.component) {
            case TOTAL:
              bar1.setValue((Integer)s.value);
              break;
            case FILE:
              bar2.setValue((Integer)s.value);
              break;
            case LOG:
              area.append((String)s.value);
              break;
            }
          }
        }
        @Override public void done() {
          runButton.setEnabled(true);
          statusPanel.removeAll();
          statusPanel.revalidate();
          String text = null;
          if(isCancelled()) {
            text = "Cancelled";
          } else {
            try {
              text = get();
            } catch(Exception ex) {
              ex.printStackTrace();
              text = "Exception";
            }
          }
          area.append(text);
          area.setCaretPosition(area.getDocument().getLength());
        }
      };
      worker.execute();
    }
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() { createAndShowGUI(); }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new TwoProgressBarsTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}
enum Target { TOTAL, FILE, LOG }
class DownloadProgress {
  public final Object value;
  public final Target component;
  public DownloadProgress(Target component, Object value) {
    this.component = component;
    this.value = value;
  }
}

答案 3 :(得分:2)

你可以走裸机路线:

每当您想要更新它时:

EventQueue.invokeLater(new Runnable(){
    public void run(){
        firstProgressBar.setValue(someInt);
        secondProgressBar.setValue(someOtherInt);
    }
});