Swing/TranslucentButton のバックアップの現在との差分(No.18)
- category: swing
folder: TranslucentButton
title: JButtonを半透明にする
tags: [JButton, Translucent, GradientPaint, Icon, Html, OverlayLayout, JLabel]
author: aterai
pubdate: 2012-12-31T06:46:18+09:00
description: 背景が透明なJButtonに半透明なIconを設定するなどして、ボタンテキスト以外が半透明なJButtonを作成します。
image:
hreflang:
href: https://java-swing-tips.blogspot.com/2013/01/make-translucent-jbutton.html lang: en
概要
背景が透明なJButton
に半透明なIcon
を設定するなどして、ボタンテキスト以外が半透明なJButton
を作成します。
Screenshot
Advertisement
サンプルコード
class TranslucentButton extends JButton {
private static final Color TL = new Color(1f, 1f, 1f, .2f);
private static final Color BR = new Color(0f, 0f, 0f, .4f);
private static final Color ST = new Color(1f, 1f, 1f, .2f);
private static final Color SB = new Color(1f, 1f, 1f, .1f);
private Color ssc;
private Color bgc;
private int r = 8;
#spanadd
#spanend
public TranslucentButton(String text) {
super(text);
}
#spanadd
#spanend
public TranslucentButton(String text, Icon icon) {
super(text, icon);
}
#spanadd
#spanend
@Override public void updateUI() {
super.updateUI();
setContentAreaFilled(false);
setFocusPainted(false);
setOpaque(false);
setForeground(Color.WHITE);
}
#spanadd
#spanend
@Override protected void paintComponent(Graphics g) {
int x = 0;
int y = 0;
int w = getWidth();
int h = getHeight();
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Shape area = new RoundRectangle2D.Float(x, y, w - 1, h - 1, r, r);
ssc = TL;
bgc = BR;
ButtonModel m = getModel();
if (m.isPressed()) {
ssc = SB;
bgc = ST;
} else if (m.isRollover()) {
ssc = ST;
bgc = SB;
}
g2.setPaint(new GradientPaint(x, y, ssc, x, y + h, bgc, true));
g2.fill(area);
g2.setPaint(BR);
g2.draw(area);
g2.dispose();
super.paintComponent(g);
}
}
View in GitHub: Java, Kotlin解説
- 透明な
JButton
、全体を半透明なIcon
、タイトルのIcon
と文字列はalign='middle'
などを指定して配置- 参考: JRadioButtonを使ってToggleButtonBarを作成
-
setOpaque(false);
、setContentAreaFilled(false);
などで、JButton
自体は透明化 - タイトル
Icon
と文字列のalign
に、top
、middle
、bottom
のどれを設定してもベースラインで揃わない -
setOpaque(false);
、setContentAreaFilled(false);
などでJButton
自体は透明化 - タイトル
Icon
と文字列のalign
にtop
、middle
、bottom
のどれを設定してもベースラインで揃わない - サイズが固定
-
MetalLookAndFeel
に変更しても、余計なBorder
が表示されない -
Html
を使っているのでGTKLookAndFeel
で、Pressed
時の文字色変更に対応していない -
MetalLookAndFeel
に変更しても余計なBorder
が表示されない -
Html
を使っているのでGTKLookAndFeel
でPressed
時の文字色変更に対応していない
private static String makeTitleWithIcon(URL u, String t, String a) {
return String.format(
"<html><p align='%s'><img src='%s' align='%s' /> %s", a, u, a, t);
}
#spanadd
#spanend
private static AbstractButton makeButton(String title) {
return new JButton(title) {
@Override public void updateUI() {
super.updateUI();
setVerticalAlignment(SwingConstants.CENTER);
setVerticalTextPosition(SwingConstants.CENTER);
setHorizontalAlignment(SwingConstants.CENTER);
setHorizontalTextPosition(SwingConstants.CENTER);
setMargin(new Insets(2, 8, 2, 8));
setBorder(BorderFactory.createEmptyBorder(2, 8, 2, 8));
//setBorderPainted(false);
// setBorderPainted(false);
setContentAreaFilled(false);
setFocusPainted(false);
setOpaque(false);
setForeground(Color.WHITE);
setIcon(new TranslucentButtonIcon());
}
};
}
- 透明な
JButton
、全体を半透明なIcon
、タイトルのIcon
と文字列はJLabel
をOverlayLayout
で配置-
Html
のalign
ではなく、Baseline
の揃ったJLabel
を半透明なJButton
に重ねて表示 -
JButton
のテキストは空なので、GTKLookAndFeel
で、Pressed
時の文字色変更に対応していない -
Html
のalign
ではなくBaseline
の揃ったJLabel
を半透明なJButton
に重ねて表示 -
JButton
のテキストは空なのでGTKLookAndFeel
でPressed
時の文字色変更に対応していない
-
JLabel label = new JLabel("JLabel", icon, SwingConstants.CENTER);
label.setForeground(Color.WHITE);
label.setAlignmentX(Component.CENTER_ALIGNMENT);
b = makeButton("");
b.setAlignmentX(Component.CENTER_ALIGNMENT);
JPanel p = new JPanel();
p.setLayout(new OverlayLayout(p));
p.setOpaque(false);
p.add(label);
p.add(b);
add(p);
- 透明な
JButton
、全体を半透明なIcon
-
setOpaque(false);
,setContentAreaFilled(false);
などを設定してJButton
は透明にし、JButton#paintComponent(...)
をオーバーライドして半透明の影などを描画 -
MetalLookAndFeel
で、余計なフチ?が表示される -
JButton#setBorderPainted(false);
で、Border
を非表示にできる -
setBorder(BorderFactory.createEmptyBorder(2, 8, 2, 8));
で設定した余白は、Icon
自体のサイズには含めないが、Icon
の描画は使用する -
JButton#setMargin(new Insets(2, 8, 2, 8));
が有効かどうかは、環境またはLookAndFeel
に依存する? -
setOpaque(false);
、setContentAreaFilled(false);
などを設定してJButton
は透明にし、JButton#paintComponent(...)
をオーバーライドして半透明の影などを描画 -
MetalLookAndFeel
で余計なフチ?が表示される -
JButton#setBorderPainted(false);
でBorder
は非表示になる -
setBorder(BorderFactory.createEmptyBorder(2, 8, 2, 8));
で設定した余白はIcon
自体のサイズには含めないがIcon
の描画は使用する -
JButton#setMargin(new Insets(2, 8, 2, 8));
が有効かどうかは環境またはLookAndFeel
に依存する?
-
class TranslucentButtonIcon implements Icon {
private static final Color TL = new Color(1f, 1f, 1f, .2f);
private static final Color BR = new Color(0f, 0f, 0f, .4f);
private static final Color ST = new Color(1f, 1f, 1f, .2f);
private static final Color SB = new Color(1f, 1f, 1f, .1f);
private static final int R = 8;
private int width;
private int height;
#spanadd
#spanend
public TranslucentButtonIcon(JComponent c) {
Insets i = c.getBorder().getBorderInsets(c);
Insets i = c.getInsets();
Dimension d = c.getPreferredSize();
width = d.width - i.left - i.right;
height = d.height - i.top - i.bottom;
}
#spanadd
#spanend
@Override public void paintIcon(Component c, Graphics g, int x, int y) {
if (c instanceof AbstractButton) {
AbstractButton b = (AbstractButton) c;
// XXX: Insets i = b.getMargin();
Insets i = b.getBorder().getBorderInsets(b);
Insets i = b.getInsets();
int w = c.getWidth();
int h = c.getHeight();
width = w - i.left - i.right;
height = h - i.top - i.bottom;
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Shape area = new RoundRectangle2D.Float(
x - i.left, y - i.top, w - 1, h - 1, R, R);
Color ssc = TL;
Color bgc = BR;
ButtonModel m = b.getModel();
if (m.isPressed()) {
ssc = SB;
bgc = ST;
} else if (m.isRollover()) {
ssc = ST;
bgc = SB;
}
g2.setPaint(new GradientPaint(0, 0, ssc, 0, h, bgc, true));
g2.fill(area);
g2.setPaint(BR);
g2.draw(area);
g2.dispose();
}
}
#spanadd
#spanend
@Override public int getIconWidth() {
return Math.max(width, 100);
}
#spanadd
#spanend
@Override public int getIconHeight() {
return Math.max(height, 20);
}
}