• 追加された行はこの色です。
  • 削除された行はこの色です。
---
category: swing
folder: TreeNodeProgressBar
title: JTreeのノードにJProgressBarを表示する
tags: [JTree, JProgressBar, DefaultTreeCellRenderer, SwingWorker, ExecutorService]
author: aterai
pubdate: 2013-12-23T01:15:16+09:00
description: JTreeのノードにJProgressBarを表示するTreeCellRendererを設定します。
image: https://lh4.googleusercontent.com/-SBg5NOTGinM/UrcLHfPzXVI/AAAAAAAAB84/HD0k-sWiJGo/s800/TreeNodeProgressBar.png
---
* 概要 [#r38f06fc]
* 概要 [#summary]
`JTree`のノードに`JProgressBar`を表示する`TreeCellRenderer`を設定します。

#download(https://lh4.googleusercontent.com/-SBg5NOTGinM/UrcLHfPzXVI/AAAAAAAAB84/HD0k-sWiJGo/s800/TreeNodeProgressBar.png)

* サンプルコード [#k25739e8]
* サンプルコード [#sourcecode]
#code(link){{
class ProgressBarRenderer extends DefaultTreeCellRenderer {
  private int nodeWidth = 100;
  private static int barHeight = 4;
  private final JProgressBar b = new JProgressBar(0, 100) {
    @Override public Dimension getPreferredSize() {
      Dimension d = super.getPreferredSize();
      d.height = barHeight;
      d.width  = nodeWidth;
      return d;
    }
    @Override public void updateUI() {
      super.updateUI();
      setUI(new BasicProgressBarUI());
    }
  };
  private final JPanel p = new JPanel(new BorderLayout());
  public ProgressBarRenderer() {
    super();
    b.setOpaque(false);
    p.setOpaque(false);
    b.setStringPainted(true);
    b.setString("");
    b.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
  }
  @Override public Component getTreeCellRendererComponent(
      JTree tree, Object value, boolean selected, boolean expanded,
      boolean leaf, int row, boolean hasFocus) {
    Object o = ((DefaultMutableTreeNode) value).getUserObject();
    JComponent c = (JComponent) super.getTreeCellRendererComponent(
        tree, value, selected, expanded, leaf, row, hasFocus);
    if (o==null || !(o instanceof ProgressObject)) {
    if (!(o instanceof ProgressObject)) {
      return c;
    }
    ProgressObject n = (ProgressObject) o;
    int i = n.getValue();
    b.setValue(i);

    FontMetrics metrics = c.getFontMetrics(c.getFont());
    int ww = getX() + getIcon().getIconWidth() + getIconTextGap()
      + metrics.stringWidth(n.title);
    nodeWidth = ww;

    p.removeAll();
    p.add(c);
    p.add(i < 100 ? b : Box.createVerticalStrut(barHeight), BorderLayout.SOUTH);
    return p;
  }
}
}}

* 解説 [#gc82b31a]
* 解説 [#explanation]
上記のサンプルでは、タスクが実行中の場合、ノードの幅(アイコンと文字列)だけの長さを持つ`JProgressBar`を配置する`TreeCellRenderer`を作成して、これを`JTree#setCellRenderer(...)`で設定しています。

- スタートボタンを押すと、`JButton`を選択不可にし、`SwingWorker`を起動して葉以外のノードをすべて捜査
- 取得した各ノードで、ダミーの`SwingWorker`を`ExecutorService#execute(...)`で起動し、進捗を`JProgressBar`を配置した`TreeCellRenderer`で表示
-- ダミータスクが終了するとそのノードを展開
- すべてのノードのタスクが終了したことを`ExecutorService#awaitTermination(...)`で検知したら、`JButton`を選択可に戻す

//* 参考リンク
* コメント [#i5011a06]
//* 参考リンク [#reference]
* コメント [#comment]
#comment
#comment