Swing/TableHeaderRolloverSeparator の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/TableHeaderRolloverSeparator へ行く。
- Swing/TableHeaderRolloverSeparator の差分を削除
--- category: swing folder: TableHeaderRolloverSeparator title: JTableHeaderのTableColumn間にロールオーバーするSeparatorを追加 tags: [JTableHeader, JLayer] author: aterai pubdate: 2024-09-16T06:28:08+09:00 description: JTableHeaderの各TableColumn間にロールオーバー時のみ出現するSeparatorをJLayerを使用して描画します。 image: https://drive.google.com/uc?id=1jKFaoPm60O8pk452XYFwtC1NgNvCwPp4 --- * 概要 [#summary] JTableHeaderの各TableColumn間にロールオーバー時のみ出現するSeparatorをJLayerを使用して描画します。 `JTableHeader`の各`TableColumn`間にロールオーバー時のみ出現する`Separator`を`JLayer`を使用して描画します。 #download(https://drive.google.com/uc?id=1jKFaoPm60O8pk452XYFwtC1NgNvCwPp4) * サンプルコード [#sourcecode] #code(link){{ 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()); } } }} * 解説 [#explanation] - `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`を非表示に変更 * 参考リンク [#reference] - [[JTableHeaderの余白にヘッダを描画する>Swing/TableHeaderFiller]] - [[JTableHeaderをリンク風に表示しセル内余白のクリックを無効にする>Swing/HyperlinkHeaderCellRenderer]] * コメント [#comment] #comment #comment