Swing/FocusBorder のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/FocusBorder へ行く。
- 1 (2023-10-30 (月) 00:34:04)
- 2 (2023-11-06 (月) 19:19:18)
- 3 (2023-11-16 (木) 14:52:51)
- category: swing folder: FocusBorder title: JTextFieldにフォーカスの有無でフチ色を変更するBorderを設定する tags: [JTextField, Focus, Border, LookAndFeel] author: aterai pubdate: 2023-10-30T00:32:37+09:00 description: JTextFieldにフォーカスが適用されたらそのフチ色を変更してハイライトするBorderを設定します。 image: https://drive.google.com/uc?id=1uxBRQ_jk5WrG6Q6E7Jqg0BaaVQFLgrYD
概要
JTextField
にフォーカスが適用されたらそのフチ色を変更してハイライトするBorder
を設定します。
Screenshot
Advertisement
サンプルコード
JTextField field2 = new JTextField(20) {
private transient FocusListener handler;
@Override public void updateUI() {
removeFocusListener(handler);
super.updateUI();
setOpaque(false);
setBorder(new RoundedCornerBorder());
handler = new FocusBorderListener();
addFocusListener(handler);
}
@Override protected void paintComponent(Graphics g) {
Border b = getBorder();
if (!isOpaque() && b instanceof RoundedCornerBorder) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setPaint(getBackground());
int w = getWidth() - 1;
int h = getHeight() - 1;
g2.fill(((RoundedCornerBorder) b).getBorderShape(0, 0, w, h));
g2.dispose();
}
super.paintComponent(g);
}
};
// ...
class RoundedCornerBorder extends AbstractBorder {
private static final Paint ALPHA_ZERO = new Color(0x0, true);
private static final int ARC = 4;
@Override public void paintBorder(
Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Shape border = getBorderShape(x, y, width - 1, height - 1);
g2.setPaint(ALPHA_ZERO);
Area corner = new Area(new Rectangle2D.Double(x, y, width, height));
corner.subtract(new Area(border));
g2.fill(corner);
Color borderColor;
if (c.hasFocus()) {
borderColor = new Color(0x4F_C1_E9);
} else if (c.isEnabled()) {
borderColor = Color.LIGHT_GRAY;
} else {
borderColor = Color.WHITE;
}
g2.setPaint(borderColor);
g2.draw(border);
g2.dispose();
}
public Shape getBorderShape(int x, int y, int w, int h) {
return new RoundRectangle2D.Double(x, y, w, h, ARC, ARC);
}
@Override public Insets getBorderInsets(Component c) {
return new Insets(ARC, ARC, ARC, ARC);
}
@Override public Insets getBorderInsets(Component c, Insets insets) {
insets.set(ARC, ARC, ARC, ARC);
return insets;
}
}
class FocusBorderListener implements FocusListener {
@Override public void focusGained(FocusEvent e) {
update(e.getComponent());
}
@Override public void focusLost(FocusEvent e) {
update(e.getComponent());
}
private void update(Component c) {
c.repaint();
}
}
View in GitHub: Java, Kotlin解説
JTextField
に角丸のBorder
を設定- この
FocusBorder
のpaintBorder(...)
メソッドをオーバーライドし、Component#hasFocus()
の場合はフチ色を変更するよう設定 - デフォルトではフォーカスの有無でフチ色が変化しない
MetalLookAndFeel
やWindowsLookAndFeel
の場合、JTextField
にフォーカスが設定されたらフチを含むコンポーネント全体を再描画するFocusListener
を追加する必要があるNimbusLookAndFeel
はFocusListener
を実装するSynthTextFieldUI.Handler
で再描画を実行しているMotifLookAndFeel
はFocusListener
ではなくDefaultCaret#focusGained(...)
などをオーバーライドして再描画を実行している
public class MotifTextUI {
public static class MotifCaret extends DefaultCaret implements UIResource {
@Override public void focusGained(FocusEvent e) {
super.focusGained(e);
getComponent().repaint();
}
@Override public void focusLost(FocusEvent e) {
super.focusLost(e);
getComponent().repaint();
}
// ...
参考リンク
- Borderのアニメーション
- JComboBoxのFocusBorderの対象を内部のアイテムではなくJComboBox自体に変更する
- JTextFieldにフォーカスがある場合の背景色を設定
- JTextFieldの角を丸める