---
category: swing
folder: FlatTable
title: JTableのヘッダやセル罫線の色を統一して罫線の幅が変化しないよう設定する
tags: [JTable, TableCellRenderer, TableCellEditor, JScrollPane]
author: aterai
pubdate: 2020-08-10T06:20:47+09:00
description: JTableのヘッダ背景色、セル罫線、セルエディタ罫線の色を統一して、セルが編集状態になっても全体の罫線の幅が変化しないよう設定します。
image: https://drive.google.com/uc?id=17yLTgJ-JfE8Pb12xmERIagJ-mQgyDao8
---
* 概要 [#summary]
`JTable`のヘッダ背景色、セル罫線、セルエディタ罫線の色を統一して、セルが編集状態になっても全体の罫線の幅が変化しないよう設定します。

#download(https://drive.google.com/uc?id=17yLTgJ-JfE8Pb12xmERIagJ-mQgyDao8)


* サンプルコード [#sourcecode]
#code(link){{
JTable table = new JTable(10, 3) {
  private final CellBorder border = new CellBorder(2, 2, 1, 2);
  @Override public Component prepareEditor(TableCellEditor editor, int row, int column) {
  @Override public Component prepareEditor(
      TableCellEditor editor, int row, int column) {
    Component c = super.prepareEditor(editor, row, column);
    if (c instanceof JTextField) {
      ((JComponent) c).setBorder(border);
      border.setStartCell(column == 0);
    }
    return c;
  }
};
table.setAutoCreateRowSorter(true);
table.setFillsViewportHeight(true);
table.setShowVerticalLines(false);
table.setGridColor(Color.ORANGE);
table.setSelectionForeground(Color.BLACK);
table.setSelectionBackground(new Color(0x64_AA_EE_FF, true));
table.setIntercellSpacing(new Dimension(0, 1));
table.setBorder(BorderFactory.createEmptyBorder());
table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
  private final CellBorder border = new CellBorder(2, 2, 1, 2);
  @Override public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus,
        int row, int column) {
    JLabel c = (JLabel) super.getTableCellRendererComponent(
        table, value, isSelected, hasFocus, row, column);
    border.setStartCell(column == 0);
    c.setBorder(border);
    return c;
  }
});

JTableHeader header = table.getTableHeader();
header.setBorder(BorderFactory.createEmptyBorder());
header.setDefaultRenderer(new DefaultTableCellRenderer() {
  private final CellBorder border = new CellBorder(2, 2, 1, 2);
  @Override public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus,
        int row, int column) {
    JLabel c = (JLabel) super.getTableCellRendererComponent(
        table, value, isSelected, hasFocus, row, column);
    border.setStartCell(column == 0);
    c.setHorizontalAlignment(SwingConstants.CENTER);
    c.setBorder(border);
    c.setBackground(table.getGridColor());
    return c;
  }
});
}}

* 解説 [#explanation]
- `JTable`
-- `JTable#setShowVerticalLines(false)`として縦罫線を非表示化
- `JTableHeader`
-- `JTable#getGridColor()`で取得した色で背景を描画するセルレンダラーを`JTableHeader#setDefaultRenderer(...)`で設定
- `TableCellRenderer`
-- 先頭セルは罫線を`4`辺非表示、それ以外のセルは左辺のみ罫線を描画する`Border`を設定したセルレンダラーを使用
- `TableCellEditor`
-- 先頭セルは罫線を`4`辺非表示、それ以外のセルは左辺のみ罫線を描画する`Border`を`JTable#prepareEditor(...)`をオーバーライドして設定
--- 参考: [[CellEditorのBorderを変更>Swing/CellEditorBorder]]
- `JScrollPane`
-- `4`辺を`JTable#getGridColor()`で取得した色で描画する`Border`を`JScrollPane#setBorder(...)`で設定
-- デフォルトの縦`ScrollBar`が表示されると最終列セルの右辺ではなく縦`ScrollBar`の右辺に罫線が描画されてしまうので`JScrollBar`を半透明化して`JTable`内部に配置するよう変更
--- 参考: [[JScrollBarをJTable上に重ねて表示するJScrollPaneを作成する>Swing/OverlappedScrollBar]]


* 参考リンク [#reference]
- [[JTableの本体、ヘッダ、親JScrollPaneなどにBorderを設定する>Swing/TableBorder]]
- [[CellEditorのBorderを変更>Swing/CellEditorBorder]]
- [[JScrollBarをJTable上に重ねて表示するJScrollPaneを作成する>Swing/OverlappedScrollBar]]
- [[JTableのセル罫線をMatteBorderで描画する>Swing/SudokuTableBorder]]
* コメント [#comment]
#comment
#comment