JTableのドラッグスクロールをタッチスクリーンで実行する
Total: 2121
, Today: 1
, Yesterday: 0
Posted by aterai at
Last-modified:
概要
JTable
のドラッグスクロールをタッチスクリーンで実行可能にするためのリスナーを作成します。
Screenshot
Advertisement
サンプルコード
class TableTouchScreenHandler extends MouseAdapter implements ListSelectionListener {
public static final int VELOCITY = 5;
public static final int DELAY = 10;
public static final double GRAVITY = .95;
private final Cursor dc = Cursor.getDefaultCursor();
private final Cursor hc = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
private final Timer scroller;
private final Point startPt = new Point();
private final Point delta = new Point();
protected TableTouchScreenHandler(JTable table) {
super();
this.scroller = new Timer(DELAY, e -> {
System.out.print(".");
JViewport vport = (JViewport) SwingUtilities.getUnwrappedParent(table);
Point vp = vport.getViewPosition();
vp.translate(-delta.x, -delta.y);
table.scrollRectToVisible(new Rectangle(vp, vport.getSize()));
if (Math.abs(delta.x) > 0 || Math.abs(delta.y) > 0) {
delta.setLocation((int) (delta.x * GRAVITY), (int) (delta.y * GRAVITY));
} else {
((Timer) e.getSource()).stop();
}
});
}
@Override public void mousePressed(MouseEvent e) {
System.out.println("mousePressed: " + delta);
Component c = e.getComponent();
c.setCursor(hc);
// c.setEnabled(false);
Container p = SwingUtilities.getUnwrappedParent(c);
if (p instanceof JViewport) {
startPt.setLocation(SwingUtilities.convertPoint(c, e.getPoint(), p));
scroller.stop();
}
}
@Override public void mouseDragged(MouseEvent e) {
Component c = e.getComponent();
Container p = SwingUtilities.getUnwrappedParent(c);
if (p instanceof JViewport) {
JViewport vport = (JViewport) p;
Point cp = SwingUtilities.convertPoint(c, e.getPoint(), vport);
Point vp = vport.getViewPosition();
vp.translate(startPt.x - cp.x, startPt.y - cp.y);
delta.setLocation(VELOCITY * (cp.x - startPt.x), VELOCITY * (cp.y - startPt.y));
((JComponent) c).scrollRectToVisible(new Rectangle(vp, vport.getSize()));
startPt.setLocation(cp);
}
}
@Override public void mouseReleased(MouseEvent e) {
System.out.println("mouseReleased: " + delta);
JTable c = (JTable) e.getComponent();
c.setCursor(dc);
// c.setEnabled(true);
if (c.isEditing()) {
delta.setLocation(0, 0);
} else {
scroller.start();
}
}
@Override public void valueChanged(ListSelectionEvent e) {
System.out.println("\nvalueChanged: " + e.getValueIsAdjusting());
if (scroller.isRunning()) {
System.out.println("isRunning");
delta.setLocation(0, 0);
}
scroller.stop();
}
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、ドラッグによるスクロールはJTableをスクロールバー無しのドラッグでスクロールすると同じマウスリスナーを使用していますが、タッチスクリーン上で実行するために以下の変更を追加しています。
- タッチした時点ではそのタッチイベントが取得できない?ため、
ListSelectionListener
を追加して行が選択されたらスクロールを中断する - タッチがドラッグではなくセル編集開始の場合はスクロール開始を実行しない
- 編集終了のタッチの場合でもスクロールが開始されないようにするため、編集開始時点で移動量を
0
に設定する必要がある - この設定をしない場合、例えば
0
列0
行目のセルを編集状態にしたあと2
列10
行目のチェックボックスをタッチすると自動スクロールが開始されてしまう
- 編集終了のタッチの場合でもスクロールが開始されないようにするため、編集開始時点で移動量を
参考リンク
- JTableをスクロールバー無しのドラッグでスクロールする
- こちらのサンプルではタッチスクリーンを指で操作した場合、セル編集やスクロールの停止に不具合がある