TITLE:JProgressBarの進捗状況を円形で表示する
#navi(../)
#tags(JProgressBar, SwingWorker)
RIGHT:Posted by &author(aterai); at 2014-06-02
* JProgressBarの進捗状況を円形で表示する [#a1079692]
`JProgressBar`の進捗状況を円形表示するように設定します。

#download
#ref(https://lh3.googleusercontent.com/-K2Us5zyEGJs/U4rt4SgHxVI/AAAAAAAACGo/IBfgQ2C1jxE/s800/ProgressCircle.png)

** サンプルコード [#q9430338]
#code(link){{
class ProgressCircleUI extends BasicProgressBarUI {
  @Override public Dimension getPreferredSize(JComponent c) {
    Dimension d = super.getPreferredSize(c);
    int v = Math.max(d.width, d.height);
    d.setSize(v, v);
    return d;
  }
  @Override public void paint(Graphics g, JComponent c) {
    Insets b = progressBar.getInsets(); // area for border
    int barRectWidth  = progressBar.getWidth()  - b.right - b.left;
    int barRectHeight = progressBar.getHeight() - b.top - b.bottom;
    if (barRectWidth <= 0 || barRectHeight <= 0) {
      return;
    }

    // draw the cells
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setPaint(progressBar.getForeground());
    double degree = 360 * progressBar.getPercentComplete();
    double sz = Math.min(barRectWidth, barRectHeight);
    double cx = b.left + barRectWidth  * .5;
    double cy = b.top  + barRectHeight * .5;
    double or = sz * .5;
    double ir = or * .5; //or - 20;
    Shape inner = new Ellipse2D.Double(cx - ir, cy - ir, ir * 2, ir * 2);
    Shape outer = new Arc2D.Double(
        cx - or, cy - or, sz, sz, 90 - degree, degree, Arc2D.PIE);
    Area area = new Area(outer);
    area.subtract(new Area(inner));
    g2.fill(area);
    g2.dispose();

    // Deal with possible text painting
    if (progressBar.isStringPainted()) {
      paintString(g, b.left, b.top, barRectWidth, barRectHeight, 0, b);
    }
  }
}
}}

** 解説 [#jf89c743]
上記のサンプルでは、`BasicProgressBarUI#paint(Graphics g, JComponent c)`をオーバーライドして進捗状況を円形で表現する`ProgressBarUI`を作成し、`JProgressBar`に設定しています。

- 注:
-- 表示上、中心から表示枠矩形の上辺中央を結ぶ線が弧の始角で、増加は時計回り方向に見えるよう`Arc2D`を作成
-- 推奨サイズが常に正方形になるように、`BasicProgressBarUI#getPreferredSize(JComponent c)`をオーバーライドしているので、方向(`SwingConstants.VERTICAL`,`SwingConstants.HORIZONTAL`)は無視される
-- 不確定状態の描画(`BasicProgressBarUI#paintDeterminate(...)`,`BasicProgressBarUI#paintIndeterminate(...)`はオーバーライドしていない)は未対応

** 参考リンク [#g7490a3c]
- [[OverlayLayoutで複数のJButtonを重ねて複合ボタンを作成>Swing/CompoundButton]]
- [[JProgressBarにUIを設定してインジケータの色を変更>Swing/GradientPalletProgressBar]]

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