JTableの行ヘッダに列ヘッダのRendererを使用する
Total: 8211
, Today: 1
, Yesterday: 0
Posted by aterai at
Last-modified:
概要
JTable
の行の描画に、JTableHeader
から取得した列ヘッダのRenderer
を適用します。
Screenshot
Advertisement
サンプルコード
class RowHeaderRenderer extends JLabel implements TableCellRenderer {
private int rollOverRowIndex = -1;
public RowHeaderRenderer(JTable table) {
super();
RollOverListener rol = new RollOverListener();
table.addMouseListener(rol);
table.addMouseMotionListener(rol);
}
@Override public Component getTableCellRendererComponent(
JTable tbl, Object val, boolean isS, boolean hasF, int row, int col) {
TableCellRenderer tcr = tbl.getTableHeader().getDefaultRenderer();
boolean f = row == rollOverRowIndex;
JLabel l = (JLabel) tcr.getTableCellRendererComponent(
tbl, val, isS, f ? f : hasF, -1, -1);
if (tcr.getClass().getName().indexOf("XPDefaultRenderer") >= 0) {
l.setOpaque(!f);
this.setIcon(new ComponentIcon(l));
return this;
} else {
return l;
}
}
class RollOverListener extends MouseAdapter {
@Override public void mouseMoved(MouseEvent e) {
JTable table = (JTable) e.getComponent();
Point pt = e.getPoint();
int col = table.columnAtPoint(pt);
int column = table.convertColumnIndexToModel(col);
if (column != 0) {
return;
}
int prevRow = rollOverRowIndex;
rollOverRowIndex = table.rowAtPoint(pt);
if (rollOverRowIndex == prevRow) {
return;
}
Rectangle repaintRect;
if (rollOverRowIndex >= 0) {
Rectangle r = table.getCellRect(rollOverRowIndex, col, false);
if (prevRow >= 0) {
repaintRect = r.union(table.getCellRect(prevRow, col, false));
} else {
repaintRect = r;
}
} else {
repaintRect = table.getCellRect(prevRow, col, false);
}
table.repaint(repaintRect);
}
@Override public void mouseExited(MouseEvent e) {
JTable table = (JTable) e.getComponent();
Point pt = e.getPoint();
int col = table.columnAtPoint(pt);
int column = table.convertColumnIndexToModel(col);
if (column != 0) {
return;
}
if (rollOverRowIndex >= 0) {
table.repaint(table.getCellRect(rollOverRowIndex, col, false));
}
rollOverRowIndex = -1;
}
}
}
class ComponentIcon implements Icon {
private final JComponent cmp;
public ComponentIcon(JComponent cmp) {
this.cmp = cmp;
}
@Override public int getIconWidth() {
return 4000; // Short.MAX_VALUE;
}
@Override public int getIconHeight() {
return cmp.getPreferredSize().height + 4; // XXX: +4 for Windows 7
}
@Override public void paintIcon(Component c, Graphics g, int x, int y) {
SwingUtilities.paintComponent(
g, cmp, (Container) c, x, y, getIconWidth(), getIconHeight());
}
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、0
列目のセルにJTable#getTableHeader()#getDefaultRenderer()
メソッドで取得したセルレンダラーを使用するTableCellRenderer
を適用しています。
- ソートアイコンが列ヘッダに表示されていても行ヘッダには表示しない
- 引数の行と列を両方
-1
に設定して、TableCellRenderer#getTableCellRendererComponent(...)
で描画用コンポーネント(JLabel
)をヘッダセルレンダラーから取得
- 引数の行と列を両方
WindowsLookAndFeel
- ロールオーバーを描画する場合は
TableCellRenderer#getTableCellRendererComponent(...)
で取得したコンポーネントを透明にする - 右と下側に余白が発生するのでヘッダセルレンダラーからサイズを変更したアイコンを作成して
JLabel#setIcon(Icon)
で表示
- ロールオーバーを描画する場合は