• 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

概要

JTreeのノードにJProgressBarを表示するTreeCellRendererを設定します。

サンプルコード

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 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;
  }
}
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、タスクが実行中の場合はノードの幅(アイコンと文字列の合計)と同じサイズのJProgressBarを配置するTreeCellRendererを作成し、これをJTree#setCellRenderer(...)で設定しています。

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

参考リンク

コメント