---
category: swing
folder: StringPaintedCellProgressBar
title: TableCellRendererに進捗文字列を設定したJProgressBarを使用する
tags: [JTable, JProgressBar, SwingWorker, TableCellRenderer]
author: aterai
pubdate: 2014-03-24T00:27:55+09:00
description: JTableのTableCellRendererとして、進捗文字列を表示するJProgressBarを設定します。
image: https://lh4.googleusercontent.com/-XSMYQI-BTU8/Uy67ZR-E4TI/AAAAAAAACCE/2zdsU6o7iA0/s800/StringPaintedCellProgressBar.png
hreflang:
    href: https://java-swing-tips.blogspot.com/2014/05/jprogressbar-in-jtable-cell-render.html
    lang: en
---
* 概要 [#summary]
`JTable`の`TableCellRenderer`として、進捗文字列を表示する`JProgressBar`を設定します。

#download(https://lh4.googleusercontent.com/-XSMYQI-BTU8/Uy67ZR-E4TI/AAAAAAAACCE/2zdsU6o7iA0/s800/StringPaintedCellProgressBar.png)

* サンプルコード [#sourcecode]
#code(link){{
class Task extends SwingWorker<Integer, ProgressValue> {
  private final int lengthOfTask;
  private final int sleepDummy = new Random().nextInt(100) + 1;
  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(sleepDummy);
        Thread.sleep(randomSleep);
      } catch (InterruptedException ie) {
        break;
      }
      publish(new ProgressValue(lengthOfTask, current));
    }
    return sleepDummy * lengthOfTask;
    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);
    }
  }
}
}}

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

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

* 参考リンク [#reference]
- [[JTableのセルにJProgressBarを表示>Swing/TableCellProgressBar]]

* コメント [#comment]
#comment
#comment