• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JButtonの形を変更
#navi(../)
*JButtonの形を変更 [#d17df847]
Posted by [[terai]] at 2007-07-02
---
category: swing
folder: RoundButton
title: JButtonの形を変更
tags: [JButton, Shape, Graphics]
author: aterai
pubdate: 2007-07-02T12:52:49+09:00
description: 円形やラウンド矩形などの任意の図形を適用したJButtonを作成します。
image: https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTSJxI6T0I/AAAAAAAAAiU/uPR0zvWSEnQ/s800/RoundButton.png
hreflang:
    href: https://java-swing-tips.blogspot.com/2008/11/rounded-corner-jbutton.html
    lang: en
---
* 概要 [#summary]
円形やラウンド矩形などの任意の図形を適用した`JButton`を作成します。

#contents
#download(https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTSJxI6T0I/AAAAAAAAAiU/uPR0zvWSEnQ/s800/RoundButton.png)

**概要 [#qed75711]
円形や角丸のJButtonを作成します。

-&jnlp;
-&jar;
-&zip;

#screenshot

**サンプルコード [#y810b25e]
#code{{
* サンプルコード [#sourcecode]
#code(link){{
class RoundedCornerButton extends JButton {
  private static final float arcwidth  = 16.0f;
  private static final float archeight = 16.0f;
  protected static final int focusstroke = 2;
  protected final Color fc = new Color(100,150,255,200);
  protected final Color ac = new Color(230,230,230);
  private static final float ARC_WIDTH = 16f;
  private static final float ARC_HEIGHT = 16f;
  protected static final int FOCUS_STROKE = 2;
  protected final Color fc = new Color(100, 150, 255, 200);
  protected final Color ac = new Color(230, 230, 230);
  protected final Color rc = Color.ORANGE;
  protected Shape shape;
  protected Shape border;
  protected Shape base;
  public RoundedCornerButton() {
    super();
  }

  public RoundedCornerButton(Icon icon) {
    super(icon);
  }

  public RoundedCornerButton(String text) {
    super(text);
    //setRolloverEnabled(true);
  }

  public RoundedCornerButton(Action a) {
    super(a);
    // setAction(a);
  }

  public RoundedCornerButton(String text, Icon icon) {
    super(text, icon);
    // setModel(new DefaultButtonModel());
    // init(text, icon);
    // setContentAreaFilled(false);
    // setBackground(new Color(250, 250, 250));
    // initShape();
  }

  @Override public void updateUI() {
    super.updateUI();
    setContentAreaFilled(false);
    setFocusPainted(false);
    setBackground(new Color(250, 250, 250));
    initShape();
  }

  protected void initShape() {
    if(!getBounds().equals(base)) {
    if (!getBounds().equals(base)) {
      base = getBounds();
      shape = new RoundRectangle2D.Float(0, 0,
                        getWidth()-1, getHeight()-1,
                        arcwidth, archeight);
      border = new RoundRectangle2D.Float(focusstroke, focusstroke,
                        getWidth()-1-focusstroke*2,
                        getHeight()-1-focusstroke*2,
                        arcwidth, archeight);
      shape = new RoundRectangle2D.Float(
          0, 0, getWidth() - 1, getHeight() - 1, ARC_WIDTH, ARC_HEIGHT);
      border = new RoundRectangle2D.Float(
          FOCUS_STROKE, FOCUS_STROKE, getWidth() - 1 - FOCUS_STROKE * 2,
          getHeight() - 1 - FOCUS_STROKE * 2, ARC_WIDTH, ARC_HEIGHT);
    }
  }
  protected void paintComponent(Graphics g) {

  private void paintFocusAndRollover(Graphics2D g2, Color color) {
    g2.setPaint(new GradientPaint(
        0, 0, color, getWidth() - 1, getHeight() - 1,
        color.brighter(), true));
    g2.fill(shape);
    g2.setColor(getBackground());
    g2.fill(border);
  }

  @Override protected void paintComponent(Graphics g) {
    initShape();
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    if(getModel().isArmed()) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    if (getModel().isArmed()) {
      g2.setColor(ac);
      g2.fill(shape);
    }else if(isRolloverEnabled() && getModel().isRollover()) {
    } else if (isRolloverEnabled() && getModel().isRollover()) {
      paintFocusAndRollover(g2, rc);
    }else if(hasFocus()) {
    } else if (hasFocus()) {
      paintFocusAndRollover(g2, fc);
    }else{
    } else {
      g2.setColor(getBackground());
      g2.fill(shape);
    }
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_OFF);
    g2.setColor(getBackground());
    super.paintComponent(g2);
    g2.dispose();
  }
  private void paintFocusAndRollover(Graphics2D g2, Color color) {
    g2.setPaint(new GradientPaint(0, 0, color,
                                  getWidth()-1, getHeight()-1, color.brighter(), true));
    g2.fill(shape);
    g2.setColor(getBackground());
    g2.fill(border);
  }
  protected void paintBorder(Graphics g) {

  @Override protected void paintBorder(Graphics g) {
    initShape();
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(getForeground());
    g2.draw(shape);
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
    g2.dispose();
  }
  protected boolean contains(int x, int y) {

  @Override public boolean contains(int x, int y) {
    initShape();
    return shape.contains(x, y);
    return shape == null ? false : shape.contains(x, y);
  }
}
}}

**解説 [#k9a59fc8]
上記のサンプルでは、ボタンの形や縁、クリック可能な範囲などをラウンド矩形に置き換えています。
-JButton#paintComponent()をオーバーライドして描画を変更
-JButton#contains()をオーバーライドしてクリック可能な範囲を変更
* 解説 [#explanation]
- 形や縁、クリック可能な領域をラウンド矩形などの`Shape`に変更したボタンを作成
-- `JButton#paintComponent()`メソッドをオーバーライドして描画を変更
-- `JButton#contains()`メソッドをオーバーライドしてマウスでクリック可能な領域を変更
- 角丸ボタンを継承して円ボタンを作成
-- 幅と高さが同じになるように`getPreferredSize()`メソッドをオーバーライド
-- 図形の初期化メソッドをオーバーライド
--- メソッド名前は適当、上記のサンプルでは`initShape()`

円ボタンは、以下のように角丸ボタンを継承して作成しています。
-PreferredSize(高さを幅と同じに)を設定
-図形の初期化メソッド((メソッド名前は適当、上記のサンプルではinitShape))をオーバーライド

#code{{
class RoundButton extends RoundedCornerButton {
  public RoundButton(String text) {
    super(text);
    setFocusPainted(false);
    Dimension size = getPreferredSize();
    size.width = size.height = Math.max(size.width, size.height);
    setPreferredSize(size);
    initShape();
  }

  @Override public Dimension getPreferredSize() {
    Dimension d = super.getPreferredSize();
    d.width = d.height = Math.max(d.width, d.height);
    return d;
  }

  protected void initShape() {
    if(!getBounds().equals(base)) {
    if (!getBounds().equals(base)) {
      base = getBounds();
      shape = new Ellipse2D.Float(0, 0, getWidth()-1, getHeight()-1);
      shape = new Ellipse2D.Float(0, 0, getWidth() - 1, getHeight() - 1);
      border = new Ellipse2D.Float(focusstroke, focusstroke,
                                   getWidth()-1-focusstroke*2,
                                   getHeight()-1-focusstroke*2);
                                   getWidth()  - 1 - focusstroke * 2,
                                   getHeight() - 1 - focusstroke * 2);
    }
  }
}
}}

**参考リンク [#f6518f76]
- [[CREATING ROUND SWING BUTTONS - JDC Tech Tips: August 26, 1999>http://java.sun.com/developer/TechTips/1999/tt0826.html#tip1]]
- http://java.sun.com/developer/TechTips/txtarchive/1999/Aug99_PatrickC.txt
* 参考リンク [#reference]
- [http://web.archive.org/web/20090805104428/http://java.sun.com/developer/TechTips/1999/tt0826.html CREATING ROUND SWING BUTTONS - JDC Tech Tips: August 26, 1999]
-- [http://web.archive.org/web/20090804054527/http://java.sun.com/developer/TechTips/txtarchive/1999/Aug99_PatrickC.txt Aug99_PatrickC.txt]
- [[ImageIconの形でJButtonを作成>Swing/RoundImageButton]]

**コメント [#wae57c9c]
* コメント [#comment]
#comment
- アイコンを追加したスクリーンショットに更新。 -- &user(aterai); &new{2008-07-10 (木) 17:25:34};

#comment