• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JButtonに9分割した画像を使用する
#navi(../)
#tags(JButton, Icon, BufferedImage, RGBImageFilter)
RIGHT:Posted by &author(aterai); at 2013-08-12
*JButtonに9分割した画像を使用する [#a1f17c92]
``JButton``を拡大縮小しても四隅などのサイズが変更しないようにように``9``分割した画像を使用します。
---
category: swing
folder: NineSliceScalingButton
title: JButtonに9分割した画像を使用する
tags: [JButton, Icon, BufferedImage, RGBImageFilter]
author: aterai
pubdate: 2013-08-12T00:58:18+09:00
description: JButtonを拡大縮小しても四隅などのサイズが変更しないようにように9分割した画像を使用します。
image: https://lh5.googleusercontent.com/-yYRfTw-3_BU/UgaFQAAiUcI/AAAAAAAABx4/koHqjZ3o36Q/s800/NineSliceScalingButton.png
hreflang:
    href: https://java-swing-tips.blogspot.com/2013/08/create-9-slice-scaling-image-jbutton.html
    lang: en
---
* 概要 [#summary]
`JButton`を拡大縮小しても四隅などのサイズが変更しないようにように`9`分割した画像を使用します。

-&jnlp;
-&jar;
-&zip;
#download(https://lh5.googleusercontent.com/-yYRfTw-3_BU/UgaFQAAiUcI/AAAAAAAABx4/koHqjZ3o36Q/s800/NineSliceScalingButton.png)

//#screenshot
#ref(https://lh5.googleusercontent.com/-yYRfTw-3_BU/UgaFQAAiUcI/AAAAAAAABx4/koHqjZ3o36Q/s800/NineSliceScalingButton.png)

**サンプルコード [#jde946d0]
* サンプルコード [#sourcecode]
#code(link){{
class NineSliceScalingIcon implements Icon {
  private final BufferedImage image;
  private final int a, b, c, d;
  private int width, height;
  public NineSliceScalingIcon(BufferedImage image, int a, int b, int c, int d) {
  private final int leftw;
  private final int rightw;
  private final int toph;
  private final int bottomh;
  private int width;
  private int height;
  protected NineSliceScalingIcon(
      BufferedImage image, int leftw, int rightw, int toph, int bottomh) {
    this.image = image;
    this.a = a;
    this.b = b;
    this.c = c;
    this.d = d;
    this.leftw = leftw;
    this.rightw = rightw;
    this.toph = toph;
    this.bottomh = bottomh;
  }

  @Override public int getIconWidth() {
    return width;
    return width; // Math.max(image.getWidth(null), width);
  }

  @Override public int getIconHeight() {
    return Math.max(image.getHeight(null), height);
  }

  @Override public void paintIcon(Component cmp, Graphics g, int x, int y) {
    Graphics2D g2 = (Graphics2D)g.create();
    g2.setRenderingHint(
        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    Insets i = ((JComponent)cmp).getBorder().getBorderInsets(cmp);
    g2.translate(x, y);

    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    Insets i = cmp instanceof Container ? ((Container) cmp).getInsets()
                                        : new Insets(0, 0, 0, 0);
    // g2.translate(x, y); // 1.8.0: work fine?
    int iw = image.getWidth(cmp);
    int ih = image.getHeight(cmp);
    width  = cmp.getWidth()-i.left-i.right;
    height = cmp.getHeight()-i.top-i.bottom;
    width  = cmp.getWidth() - i.left - i.right;
    height = cmp.getHeight() - i.top - i.bottom;

    g2.drawImage(image.getSubimage(a, c, iw - a - b, ih - c - d),
                 a, c, width - a - b, height - c - d, cmp);
    g2.drawImage(
        image.getSubimage(leftw, toph, iw - leftw - rightw, ih - toph - bottomh),
        leftw, toph, width - leftw - rightw, height - toph - bottomh, cmp);
    if (leftw > 0 && rightw > 0 && toph > 0 && bottomh > 0) {
      g2.drawImage(image.getSubimage(leftw, 0, iw - leftw - rightw, toph),
                   leftw, 0, width - leftw - rightw, toph, cmp);
      g2.drawImage(image.getSubimage(leftw, ih - bottomh, iw - leftw - rightw, bottomh),
                   leftw, height - bottomh, width - leftw - rightw, bottomh, cmp);
      g2.drawImage(image.getSubimage(0, toph, leftw, ih - toph - bottomh),
                   0, toph, leftw, height - toph - bottomh, cmp);
      g2.drawImage(image.getSubimage(iw - rightw, toph, rightw, ih - toph - bottomh),
                   width - rightw, toph, rightw, height - toph - bottomh, cmp);

    if(a>0 && b>0 && c>0 && d>0) {
      g2.drawImage(image.getSubimage(a, 0, iw - a - b, c),
                   a, 0, width - a - b, c, cmp);
      g2.drawImage(image.getSubimage(a, ih - d, iw - a - b, d),
                   a, height - d, width - a - b, d, cmp);
      g2.drawImage(image.getSubimage(0, c, a, ih - c - d),
                   0, c, a, height - c - d, cmp);
      g2.drawImage(image.getSubimage(iw - b, c, b, ih - c - d),
                   width - b, c, b, height - c - d, cmp);

      g2.drawImage(image.getSubimage(0, 0, a, c), 0, 0, cmp);
      g2.drawImage(image.getSubimage(iw - b, 0, b, c), width - b, 0, cmp);
      g2.drawImage(image.getSubimage(0, ih - d, a, d), 0, height - d, cmp);
      g2.drawImage(image.getSubimage(iw - b, ih - d, b, d), width - b, height - d, cmp);
      g2.drawImage(image.getSubimage(0, 0, leftw, toph),
                   0, 0, cmp);
      g2.drawImage(image.getSubimage(iw - rightw, 0, rightw, toph),
                   width - rightw, 0, cmp);
      g2.drawImage(image.getSubimage(0, ih - bottomh, leftw, bottomh),
                   0, height - bottomh, cmp);
      g2.drawImage(image.getSubimage(iw - rightw, ih - bottomh, rightw, bottomh),
                   width - rightw, height - bottomh, cmp);
    }
    g2.dispose();
  }
}
}}

**解説 [#ke8c296f]
上記のサンプルでは、``BufferedImage#getSubimage``で元画像を``9``分割し、四隅はサイズ変更なし、上下辺は幅のみ拡大縮小、左右辺は高さのみ拡大縮小、中央は幅高さが拡大縮小可能になるよう、``Graphics#drawImage(...)``のスケーリングを利用して描画しています。
* 解説 [#explanation]
上記のサンプルでは、`BufferedImage#getSubimage(...)`メソッドで元画像を`9`分割し、`4`隅はサイズ変更なし、上下辺は幅のみ拡大縮小、左右辺は高さのみ拡大縮小、中央は幅高さが拡大縮小可能になるように`Graphics#drawImage(...)`メソッドのスケーリングを利用して描画しています。

- 四隅などの固定サイズ
-- ``a``: 左上下隅の幅
-- ``b``: 右上下隅の幅
-- ``c``: 左右上隅の高さ
-- ``d``: 左右下隅の高さ
- `4`隅などの固定サイズ
-- `leftw`: 左側、上下隅の幅
-- `rightw`: 右側、上下隅の幅
-- `toph`: 上側、左右隅の高さ
-- `bottomh`: 下側、左右隅の高さ

**参考リンク [#t0591086]
- [http://rwillustrator.blogspot.jp/2007/04/understanding-9-slice-scaling.html Real World Illustrator: Understanding 9-Slice Scaling]
-- 画像(``symbol_scale_2.jpg``)を拝借しています。
* 参考リンク [#reference]
- [https://docs.oracle.com/javase/jp/8/docs/api/java/awt/image/BufferedImage.html#getSubimage-int-int-int-int- BufferedImage#getSubimage(int, int, int, int) (Java Platform SE 8)]
- [https://rwillustrator.blogspot.jp/2007/04/understanding-9-slice-scaling.html Real World Illustrator: Understanding 9-Slice Scaling]
-- テスト用の画像(`symbol_scale_2.jpg`)を拝借

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