JTableHeaderのTableColumn間にロールオーバーするSeparatorを追加
Total: 108
, Today: 1
, Yesterday: 0
Posted by aterai at
Last-modified:
概要
JTableHeader
の各TableColumn
間にロールオーバー時のみ出現するSeparator
をJLayer
を使用して描画します。
Screenshot
Advertisement
サンプルコード
class TableHeaderRolloverLayerUI extends LayerUI<JScrollPane> {
private boolean rollover;
@Override public void paint(Graphics g, JComponent c) {
super.paint(g, c);
if (c instanceof JLayer && rollover) {
JScrollPane scroll = (JScrollPane) ((JLayer<?>) c).getView();
JTable table = (JTable) scroll.getViewport().getView();
JTableHeader header = table.getTableHeader();
TableColumnModel cm = header.getColumnModel();
Graphics2D g2 = (Graphics2D) g.create();
g2.setPaint(Color.GRAY);
Line2D s = new Line2D.Double();
int size = cm.getColumnCount();
double gap = 2d;
for (int i = 0; i < size; i++) {
Rectangle r = header.getHeaderRect(i);
double y1 = r.getY() + gap;
double y2 = r.getY() + r.getHeight() - gap - gap;
s.setLine(r.getX(), y1, r.getX(), y2);
if (i != 0) {
g2.draw(s);
}
if (i < size - 1) {
double xx = r.getX() + r.getWidth() - gap;
s.setLine(xx, y1, xx, y2);
g2.draw(s);
}
}
g2.dispose();
}
}
@Override public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(
AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
}
@Override public void uninstallUI(JComponent c) {
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(0);
}
super.uninstallUI(c);
}
@Override protected void processMouseEvent(
MouseEvent e, JLayer<? extends JScrollPane> l) {
super.processMouseEvent(e, l);
Component c = e.getComponent();
if (e.getID() == MouseEvent.MOUSE_RELEASED) {
rollover = c.getBounds().contains(e.getPoint());
c.repaint();
}
}
@Override protected void processMouseMotionEvent(
MouseEvent e, JLayer<? extends JScrollPane> l) {
super.processMouseMotionEvent(e, l);
Component c = e.getComponent();
int id = e.getID();
boolean b = id == MouseEvent.MOUSE_MOVED || id == MouseEvent.MOUSE_DRAGGED;
rollover = b && c instanceof JTableHeader;
l.repaint(c.getBounds());
}
}
View in GitHub: Java, Kotlin解説
JTableHeader#setDefaultRenderer(...)
でLookAndFeel
デフォルトのBorder
やフォーカス描画を除去したフラットなセルレンダラーを設定JTable#setShowGrid(false)
などはJTableHeader
のグリッド表示などには影響しない
JTable
を配置したJScrollPane
にJLayer
をラップして現在ロールオーバー状態のTableColumn
だけではなくすべてのTableColumn
間にSeparator
を描画するLayerUI#installUI()
でAWTEvent.MOUSE_EVENT_MASK
とAWTEvent.MOUSE_MOTION_EVENT_MASK
を設定してマウスイベントをJLayer
で取得するよう設定LayerUI#processMouseMotionEvent(...)
などでJTableHeader
上にマウスカーソルが乗ったらロールオーバー状態をtrue
に設定してJTableHeader
をリペイントLayerUI#paint()
をオーバーライドしてJTableHeader
がロールオーバー状態の場合はJTableHeader#getHeaderRect(int)
で取得した各領域の左右辺にLine2D
でSeparator
を描画TableColumn
をリサイズ中にJTableHeader
外でマウスリリースした場合はSeparator
を非表示に変更