概要

JTableTableCellRendererとして、進捗文字列を表示するJProgressBarを設定します。

サンプルコード

class Task extends SwingWorker<Integer, ProgressValue> {
  private final int lengthOfTask;
  private final int randomSleep = new Random().nextInt(100) + 1;
  public Task(int lengthOfTask) {
    super();
    this.lengthOfTask = lengthOfTask;
  }

  @Override protected Integer doInBackground() {
    int current = 0;
    while (current < lengthOfTask && !isCancelled()) {
      current++;
      try {
        Thread.sleep(randomSleep);
      } catch (InterruptedException ie) {
        break;
      }
      publish(new ProgressValue(lengthOfTask, current));
    }
    return randomSleep * lengthOfTask;
  }
}

class ProgressValue {
  private final Integer progress;
  private final Integer lengthOfTask;
  public ProgressValue(Integer lengthOfTask, Integer progress) {
    this.progress = progress;
    this.lengthOfTask = lengthOfTask;
  }

  public Integer getProgress() {
    return progress;
  }

  public Integer getLengthOfTask() {
    return lengthOfTask;
  }
}

class ProgressRenderer extends DefaultTableCellRenderer {
  private final JProgressBar progress = new JProgressBar();
  private final JPanel renderer = new JPanel(new BorderLayout());
  @Override public Component getTableCellRendererComponent(
      JTable table, Object value, boolean isSelected, boolean hasFocus,
      int row, int column) {
    Component c;
    renderer.removeAll();
    progress.setValue(0);
    if (value instanceof ProgressValue) {
      ProgressValue pv = (ProgressValue) value;
      Integer current = pv.getProgress();
      Integer lengthOfTask = pv.getLengthOfTask();
      if (current < 0) {
        c = super.getTableCellRendererComponent(
            table, "Canceled", isSelected, hasFocus, row, column);
      } else if (current < lengthOfTask) {
        progress.setValue(current * 100 / lengthOfTask);
        progress.setStringPainted(true);
        progress.setString(String.format("%d/%d", current, lengthOfTask));
        renderer.add(progress);
        c = renderer;
      } else {
        c = super.getTableCellRendererComponent(
                table, "Done", isSelected, hasFocus, row, column);
      }
    } else {
      c = super.getTableCellRendererComponent(
              table, "Waiting...", isSelected, hasFocus, row, column);
    }
    return c;
  }

  @Override public void updateUI() {
    super.updateUI();
    setOpaque(true);
    if (Objects.nonNull(renderer)) {
      SwingUtilities.updateComponentTreeUI(renderer);
    }
  }
}
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、2列目のTableCellRendererとしてJProgressBar#setStringPainted(true)で進捗文字列を表示するように設定したJProgressBarを使用しています。

  • 進捗状況文字列は「現在値/最大値」の形式で表示するため、この2つの値を保持するProgressValueオブジェクトを作成してSwingWorker#publish(...)メソッドでJTableのモデルに設定
  • TableCellRendererはモデルから取得したProgressValueオブジェクトから以下の3つの値をJProgressBarに設定し、セルの描画用コンポーネントとして使用
    • JProgressBar#setMaximum(int)(最大値は各行ごとにランダムなので)で最大値を設定
    • JProgressBar#setValue(int)で現在値を設定
    • 上記の値から生成した進捗状況文字列をJProgressBar#setString(String)で設定

参考リンク

コメント