обновление ДВУХ JProgressBars

Итак, у меня это работает с ONE JProgressBar. Как обновить два отдельных индикатора выполнения? Я выполняю загрузку в методе рабочего потока doInBackground()/swingworker. Хочу обновить два бара, первый итог, второй раздел итога. Например, 21/100//всего 21/50/половины

Я уже задавал вопрос здесь и, наконец, разобрался с этой штукой. Теперь я хочу, так сказать, поднять ставку и получить два индикатора прогресса. Спасибо за чтение, ~Kyte


person Kyte    schedule 24.07.2012    source источник
comment
Этот пример обновил несколько столбцов в JTable.   -  person trashgod    schedule 25.07.2012


Ответы (4)


Вы можете пойти по маршруту с голым металлом:

Всякий раз, когда вы хотите, чтобы он обновлялся:

EventQueue.invokeLater(new Runnable(){
    public void run(){
        firstProgressBar.setValue(someInt);
        secondProgressBar.setValue(someOtherInt);
    }
});
person Charlie    schedule 24.07.2012
comment
Это было самое быстрое (и самое надежное) исправление, учитывая то, как я настроил свой класс. Спасибо всем, кто прокомментировал! - person Kyte; 25.07.2012

Вы можете воспользоваться поддержкой изменения свойства, запустив новое событие изменения свойства при обновлении хода выполнения «раздела».

Есть несколько способов добиться этого, в зависимости от имеющейся у вас информации.

Вы можете вызвать его напрямую, используя что-то вроде

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

    }

}
person MadProgrammer    schedule 24.07.2012

Вы можете воспользоваться параметром типа SwingWorker<T,V> V, который используется для получения промежуточных результатов в методах publish и process. Например:

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
        }
    }
}
person tenorsax    schedule 24.07.2012

Вот быстрый пример, который (@Max уже сказал):

введите здесь описание изображения

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;
  }
}
person aterai    schedule 24.07.2012