• 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

概要

JButtonを拡大縮小しても四隅などのサイズが変更しないようにように9分割した画像を使用します。

サンプルコード

class NineSliceScalingIcon implements Icon {
  private final BufferedImage image;
  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.leftw = leftw;
    this.rightw = rightw;
    this.toph = toph;
    this.bottomh = bottomh;
  }

  @Override public int getIconWidth() {
    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;
    if (cmp instanceof JComponent) {
      i = ((JComponent) cmp).getBorder().getBorderInsets(cmp);
    } else {
      i = 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;

    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);

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

解説

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

  • 4隅などの固定サイズ
    • leftw: 左側、上下隅の幅
    • rightw: 右側、上下隅の幅
    • toph: 上側、左右隅の高さ
    • bottomh: 下側、左右隅の高さ

参考リンク

コメント