Swing/ResizeRowHeightByDragging のバックアップ(No.5)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/ResizeRowHeightByDragging へ行く。
- 1 (2021-03-15 (月) 01:16:03)
- 2 (2021-03-15 (月) 11:03:03)
- 3 (2021-03-15 (月) 17:24:20)
- 4 (2021-03-16 (火) 01:35:51)
- 5 (2021-04-12 (月) 13:51:58)
- category: swing folder: ResizeRowHeightByDragging title: JTableの行の高さをマウスドラッグで変更する tags: [JTable, JLayer] author: aterai pubdate: 2021-03-15T01:13:19+09:00 description: JLayerを使用してJTableの行の高さをマウスでドラッグして変更可能にします。 image: https://drive.google.com/uc?id=13pGaQRMVHPUjiHSb-vmtYiQP14rpzJ6Y
概要
JLayer
を使用してJTable
の行の高さをマウスでドラッグして変更可能にします。
Screenshot
Advertisement
サンプルコード
class RowHeightResizeLayer extends LayerUI<JScrollPane> {
private static final int MIN_ROW_HEIGHT = 16;
private static final Cursor RESIZE_CURSOR = Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR);
private int mouseYOffset;
private int resizingRow = -1;
private Cursor otherCursor = RESIZE_CURSOR;
@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) {
Component c = e.getComponent();
if (c instanceof JTable) {
JTable table = (JTable) c;
resizingRow = getResizeTargetRow(table, e.getPoint());
if (e.getID() == MouseEvent.MOUSE_PRESSED && resizingRow >= 0) {
mouseYOffset = e.getY() - table.getRowHeight(resizingRow);
e.consume();
}
}
}
@Override protected void processMouseMotionEvent(MouseEvent e, JLayer<? extends JScrollPane> l) {
Component c = e.getComponent();
if (!(c instanceof JTable)) {
return;
}
JTable table = (JTable) c;
if (e.getID() == MouseEvent.MOUSE_MOVED) {
boolean isResizing = RESIZE_CURSOR.equals(table.getCursor());
int row = getResizeTargetRow(table, e.getPoint());
if (row >= 0 != isResizing) {
Cursor tmp = table.getCursor();
table.setCursor(otherCursor);
otherCursor = tmp;
}
} else if (e.getID() == MouseEvent.MOUSE_DRAGGED && resizingRow >= 0) {
int newHeight = e.getY() - mouseYOffset;
if (newHeight > MIN_ROW_HEIGHT) {
table.setRowHeight(resizingRow, newHeight);
}
e.consume();
}
}
private int getResizeTargetRow(JTable table, Point p) {
int row = table.rowAtPoint(p);
int col = table.columnAtPoint(p);
Rectangle r = table.getCellRect(row, col, false);
r.grow(0, -2);
if (r.contains(p)) {
return -1;
}
return p.y < r.getCenterY() ? row - 1 : row;
}
}
View in GitHub: Java, Kotlin解説
JTable
の各行の高さはJTable#setRowHeight(row, height)
で設定可能JTable
に直接MouseMotionListener
とMouseListener
を設定して行の高さを変更する方法もある- java - Adjusting individual row height using cursor on JTable - Stack Overflow
- 高さ変更のドラッグ方向によってセル選択状態などが変化する場合がある
JTable
の親JScrollPane
にJLayer
を設定してJTable
へのマウスイベントを取得し、高さ変更のドラッグ中はMouseEvent#consume()
を実行してJTable
へのマウスイベントを消費し、セルの選択状態が変化しないよう設定JTableHeader
の高さも同様のJLayer
でリサイズ可能だが拡大するときにフォーカスの描画が乱れる場合があるExcel
風に現在の行の高さを表示したい場合はJToolTip
がTableColumnのリサイズ中にその幅をJToolTipで表示するのように使用可能- 列幅のリサイズと同様に
JTable
外のJTableHeader
領域などにドラッグしてもリサイズを継続するよう修正