概要

WindowsLookAndFeel環境でJButtonの背景色を変更する方法をテストします。

サンプルコード

JButton button4 = new JButton("JLayer + RGBImageFilter");
JComponent c = new JLayer<>(button4, new ImageFilterLayerUI<>(new ColorFilter()));
// ...
class ImageFilterLayerUI<V extends Component> extends LayerUI<V> {
  private final transient ImageFilter filter;
  private transient BufferedImage buf;

  protected ImageFilterLayerUI(ImageFilter filter) {
    super();
    this.filter = filter;
  }

  @Override public void paint(Graphics g, JComponent c) {
    if (c instanceof JLayer) {
      Dimension d = ((JLayer<?>) c).getView().getSize();
      buf = Optional.ofNullable(buf)
          .filter(bi -> bi.getWidth() == d.width && bi.getHeight() == d.height)
          .orElseGet(() -> new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB));
      Graphics2D g2 = buf.createGraphics();
      super.paint(g2, c);
      g2.dispose();
      Image image = c.createImage(new FilteredImageSource(buf.getSource(), filter));
      g.drawImage(image, 0, 0, null);
    } else {
      super.paint(g, c);
    }
  }
}

class ColorFilter extends RGBImageFilter {
  @Override public int filterRGB(int x, int y, int argb) {
    int r = 0xFF; // (argb >> 16) & 0xFF;
    int g = (argb >> 8) & 0xFF;
    int b = argb & 0xFF;
    return (argb & 0xFF_00_00_00) | (r << 16) | (g << 8) | b;
  }
}
View in GitHub: Java, Kotlin

解説

  • Default
    • 背景色変更なしのデフォルトJButton
  • setBackground
    • JButton#setBackground(...)で背景色を変更
    • WindowsLookAndFeelの場合ボタンの外周にのみ背景色が着く
  • override paintComponent
    • JButton#setContentAreaFilled(false)を設定し、さらにJButton#paintComponent(...)をオーバーライドして独自にボタン背景やフチを描画
      JButton button2 = new JButton("override paintComponent") {
        @Override protected void paintComponent(Graphics g) {
          // paint background, border
          // ...
          super.paintComponent(g);
        }
      };
      button2.setContentAreaFilled(false);
      
  • setIcon + setPressedIcon
    • サイズが0で自身の背景ではなく親コンポーネントの背景を描画するIconを作成し、JButton#setIcon(...)JButton#setPressedIcon(...)で設定
      JButton button3 = new JButton("setIcon + setPressedIcon");
      button3.setBackground(bg1);
      button3.setBorderPainted(false);
      button3.setIcon(new ButtonBackgroundIcon(bg2));
      button3.setPressedIcon(new ButtonBackgroundIcon(bg1));
      // button3.setHorizontalTextPosition(SwingConstants.CENTER);
      

参考リンク

コメント