Swing/RoundedCornerTableRowSelection のバックアップ(No.3)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/RoundedCornerTableRowSelection へ行く。
- 1 (2024-04-08 (月) 04:33:48)
- 2 (2024-04-08 (月) 11:15:53)
- 3 (2024-08-12 (月) 08:32:09)
- category: swing folder: RoundedCornerTableRowSelection title: JTableの行選択背景描画をラウンド矩形に変更する tags: [JTable, TableCellRenderer] author: aterai pubdate: 2024-04-08T04:32:15+09:00 description: JTableの行選択背景が行全体でラウンド矩形になるよう先頭・末尾セルのTableCellRendererで角を丸めて描画します。 image: https://drive.google.com/uc?id=1qsuWnjpaJmbyjNO6RsU9kv_JSIUpxTGY
概要
JTable
の行選択背景が行全体でラウンド矩形になるよう先頭・末尾セルのTableCellRenderer
で角を丸めて描画します。
Screenshot
Advertisement
サンプルコード
class RoundSelectionRenderer extends DefaultTableCellRenderer {
private static final double ARC = 6d;
private Position pos;
@Override public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(getBackground().brighter());
double w = getWidth() - 1d;
double h = getHeight() - 1d;
Area area = pos.getArea(w, h, ARC);
g2.fill(area);
if (isFocusable()) {
g2.setColor(getBackground());
g2.draw(area);
}
super.paintComponent(g);
g2.dispose();
}
@Override public Component getTableCellRendererComponent(
JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
Component c = super.getTableCellRendererComponent(
table, value, isSelected, false, row, column);
if (c instanceof JLabel) {
JLabel l = (JLabel) c;
l.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
l.setOpaque(false);
pos = getPosition(table, column);
boolean b = value instanceof Number;
l.setHorizontalAlignment(b ? RIGHT : LEFT);
}
c.setFocusable(hasFocus
|| table.getSelectionModel().getLeadSelectionIndex() == row);
return c;
}
private static Position getPosition(JTable table, int column) {
boolean isFirst = column == 0;
boolean isLast = column == table.getColumnCount() - 1;
Position p;
if (isFirst) {
p = Position.FIRST;
} else if (isLast) {
p = Position.LAST;
} else {
p = Position.MIDDLE;
}
return p;
}
private enum Position {
FIRST, MIDDLE, LAST;
public Area getArea(double w, double h, double arc) {
Area area = new Area();
if (this == FIRST) {
area.add(new Area(new Rectangle2D.Double(w - arc, 0d, arc + arc, h)));
area.add(new Area(new RoundRectangle2D.Double(0d, 0d, w, h, arc, arc)));
} else if (this == LAST) {
area.add(new Area(new Rectangle2D.Double(-arc, 0d, arc + arc, h)));
area.add(new Area(new RoundRectangle2D.Double(0d, 0d, w, h, arc, arc)));
} else {
area.add(new Area(new Rectangle2D.Double(-arc, 0d, w + arc + arc, h)));
}
return area;
}
}
}
View in GitHub: Java, Kotlin解説
JTable#setShowGrid(false)
で罫線を非表示、JTable#setRowHeight(24)
で行の高さを拡大、JTable#setIntercellSpacing(new Dimension(0, 3))
で列の隙間を0
に縮小、行の隙間を3
に拡大して行選択描画が重ならないよう設定(Windows 11
のファイルエクスプローラー風)DefaultTableCellRenderer#paintComponent(...)
をオーバーライドして先頭、末尾、それ以外のセルで選択背景の描画を変更- 先頭セル(
column == 0
)の場合は左端をRoundRectangle2D
、右端をセル幅を右側方向にはみ出すRectangle2D
で作成したArea
で選択背景を描画- フォーカス用の罫線も上記の
Area
を使用して描画 - 右端の罫線はセル外で非表示になり、となりのセルと連続しているように表示される
- フォーカス用の罫線も上記の
- 末尾セル(
column == table.getColumnCount() - 1
)の場合は右端をRoundRectangle2D
、左端をセル幅を左側方向にはみ出すRectangle2D
で作成したArea
で選択背景を描画- 先頭セル同様、左端の罫線はセル外で非表示
- それ以外の中間セルの場合そのセル領域を左右にはみ出す
Rectangle2D
を作成して選択背景として描画- 左右の罫線はセル外で非表示
- 先頭セル(
参考リンク
- JTableHeaderの角を丸める
- 同様に先頭・末尾ヘッダセルの
TableCellRenderer
で角を丸めているが、ヘッダなのでフォーカス罫線は考慮していない
- 同様に先頭・末尾ヘッダセルの