TitledBorderのタイトル背景とボーダーの角を丸める
Total: 56
, Today: 4
, Yesterday: 2
Posted by aterai at
Last-modified:
Summary
TitledBorder
のタイトル背景を右下隅を丸めたラウンド矩形で塗りつぶし、ボーダーも四隅を丸めたラウンド矩形で描画します。
Screenshot

Advertisement
Source Code Examples
class RoundedTitledBorder extends TitledBorder {
private final JLabel label = new JLabel(" ");
private final int arc;
protected RoundedTitledBorder(String title, int arc) {
super(new RoundedBorder(arc), title);
this.arc = arc;
}
@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);
Border b = getBorder();
if (b instanceof RoundedBorder) {
Dimension d = getLabel(c).getPreferredSize();
Insets i = b.getBorderInsets(c);
int a2 = arc * 2;
int w = d.width + i.left + i.right + a2;
int h = d.height + i.top + i.bottom;
g2.setClip(((RoundedBorder) b).getBorderShape(
x + i.left, y + i.top, w, h));
g2.setPaint(Color.GRAY);
Shape titleBg = new RoundRectangle2D.Float(
x - a2, y - a2, w + a2, h + a2, arc, arc);
g2.fill(titleBg);
g2.dispose();
}
g2.dispose();
super.paintBorder(c, g, x, y, width, height);
}
private JLabel getLabel(Component c) {
this.label.setText(getTitle());
this.label.setFont(getFont(c));
this.label.setComponentOrientation(c.getComponentOrientation());
this.label.setEnabled(c.isEnabled());
return this.label;
}
}
class RoundedBorder extends EmptyBorder {
private static final Paint ALPHA_ZERO = new Color(0x0, true);
private final int arc;
protected RoundedBorder(int arc) {
super(2, 2, 2, 2);
this.arc = arc;
}
@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, height);
g2.setPaint(ALPHA_ZERO);
Area clear = new Area(new Rectangle2D.Double(x, y, width, height));
clear.subtract(new Area(border));
g2.fill(clear);
g2.setPaint(Color.GRAY);
g2.setStroke(new BasicStroke(1.5f));
g2.draw(border);
g2.dispose();
}
protected Shape getBorderShape(int x, int y, int w, int h) {
return new RoundRectangle2D.Double(x, y, w - 1, h - 1, arc, arc);
}
}
View in GitHub: Java, KotlinExplanation
RoundedTitledBorder
- TitledBorder(Border, String)でボーダーを角丸の
RoundedBorder
を使用するTitledBorder
を生成- この
RoundedBorder
はJTextFieldの角を丸めるなどで作成した角丸ボーダーと同一
- この
- さらに
TitledBorder#paintBorder(...)
をオーバーライドして右下隅を丸めたラウンド矩形をタイトル文字列の背景に描画
- TitledBorder(Border, String)でボーダーを角丸の
TitleLayerUI
TitledBorder
は使用せず、RoundedBorder
を設定してボーダーを角丸に設定し、タイトルはJLayer
で描画するよう設定LayerUI#paint(...)
をオーバーライドしてコンポーネント内部にタイトル文字列を描画- コンポーネントのフォーカスの有無でタイトル文字列の表示・非表示を切り替えるよう
LayerUI#paint(...)
内で設定し、LayerUI#processFocusEvent
もオーバーライドしてフォーカス移動イベントが発生したらコンポーネント全体を再描画してボーダーとタイトル文字列を更新
class TitleLayerUI extends LayerUI<JScrollPane> {
private final JLabel label;
protected TitleLayerUI(String title, int arc) {
super();
label = new RoundedLabel(title, arc);
label.setBorder(BorderFactory.createEmptyBorder(2, 10, 2, 10));
// label.setOpaque(false);
label.setForeground(Color.WHITE);
label.setBackground(Color.GRAY);
}
@Override public void paint(Graphics g, JComponent c) {
super.paint(g, c);
if (c instanceof JLayer) {
JScrollPane sp = (JScrollPane) ((JLayer<?>) c).getView();
Rectangle r = SwingUtilities.calculateInnerArea(sp, sp.getBounds());
if (r != null && !sp.getViewport().getView().hasFocus()) {
Dimension d = label.getPreferredSize();
SwingUtilities.paintComponent(
g, label, sp, r.x - 1, r.y - 1, d.width, d.height);
}
}
}
@Override public void updateUI(JLayer<? extends JScrollPane> l) {
super.updateUI(l);
SwingUtilities.updateComponentTreeUI(label);
}
@Override public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(AWTEvent.FOCUS_EVENT_MASK);
}
}
@Override public void uninstallUI(JComponent c) {
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(0);
}
super.uninstallUI(c);
}
@Override protected void processFocusEvent(
FocusEvent e, JLayer<? extends JScrollPane> l) {
super.processFocusEvent(e, l);
l.getView().repaint();
}
private static class RoundedLabel extends JLabel {
private final int arc;
public RoundedLabel(String title, int arc) {
super(title);
this.arc = arc;
}
@Override protected void paintComponent(Graphics g) {
if (!isOpaque()) {
Dimension d = getPreferredSize();
int w = d.width - 1;
int h = d.height - 1;
int h2 = h / 2;
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(getBackground());
g2.fillRect(0, 0, w, h2);
g2.fillRoundRect(-arc, 0, w + arc, h, arc, arc);
g2.dispose();
}
super.paintComponent(g);
}
}
}