Swing/RoundedCornerTableRowSelection の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/RoundedCornerTableRowSelection へ行く。
- Swing/RoundedCornerTableRowSelection の差分を削除
--- 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 --- * 概要 [#summary] `JTable`の行選択背景が行全体でラウンド矩形になるよう先頭・末尾セルの`TableCellRenderer`で角を丸めて描画します。 #download(https://drive.google.com/uc?id=1qsuWnjpaJmbyjNO6RsU9kv_JSIUpxTGY) * サンプルコード [#sourcecode] #code(link){{ 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; } } } }} * 解説 [#explanation] - `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`を作成して選択背景として描画 --- 左右の罫線はセル外で非表示 * 参考リンク [#reference] - [[JTableHeaderの角を丸める>Swing/RoundedCornerTableHeader]] -- 同様に先頭・末尾ヘッダセルの`TableCellRenderer`で角を丸めているが、ヘッダなのでフォーカス罫線は考慮していない - [[JTableのセル選択背景描画をラウンド矩形に変更する>Swing/RoundedCellSelectionTable]] -- 行選択ではなくセル選択でラウンド矩形化するサンプル * コメント [#comment] #comment #comment