Swing/KineticScrolling のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/KineticScrolling へ行く。
- 1 (2010-08-16 (月) 13:34:26)
- 2 (2010-08-17 (火) 12:51:12)
- 3 (2011-10-03 (月) 18:08:23)
- 4 (2012-12-28 (金) 12:38:39)
- 5 (2014-12-02 (火) 01:49:49)
- 6 (2014-12-30 (火) 15:27:03)
- 7 (2016-03-04 (金) 13:37:58)
- 8 (2017-03-29 (水) 19:49:24)
- 9 (2018-02-20 (火) 15:30:45)
- 10 (2018-02-24 (土) 19:51:30)
- 11 (2020-01-29 (水) 18:50:11)
- 12 (2021-05-09 (日) 03:05:32)
- 13 (2025-01-03 (金) 08:57:02)
- 14 (2025-01-03 (金) 09:01:23)
- 15 (2025-01-03 (金) 09:02:38)
- 16 (2025-01-03 (金) 09:03:21)
- 17 (2025-01-03 (金) 09:04:02)
TITLE:JScrollPaneでキネティックスクロール
Posted by terai at 2010-08-16
JScrollPaneでキネティックスクロール
JScrollPaneでキネティックスクロール(慣性スクロール)風の動作をするマウスリスナーを設定します。
- &jnlp;
- &jar;
- &zip;
#screenshot
サンプルコード
class KineticScrollingListener2 extends MouseAdapter {
private static final int SPEED = 6;
private static final double D = 0.7;
private final Cursor dc;
private final Cursor hc = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
private final javax.swing.Timer inside;
private final javax.swing.Timer outside;
private final JComponent label;
private Point startPt = new Point();
private Point delta = new Point();
private static boolean isInside(JViewport vport, JComponent comp) {
Point vp = vport.getViewPosition();
return (vp.x>=0 && vp.x+vport.getWidth()-comp.getWidth()<=0 &&
vp.y>=0 && vp.y+vport.getHeight()-comp.getHeight()<=0);
}
public KineticScrollingListener2(JComponent comp) {
this.label = comp;
this.dc = comp.getCursor();
this.inside = new javax.swing.Timer(20, new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
JViewport vport = (JViewport)label.getParent();
Point vp = vport.getViewPosition();
//System.out.format("s: %s, %s\n", delta, vp);
vp.translate(-delta.x, -delta.y);
vport.setViewPosition(vp);
if (Math.abs(delta.x)>0 || Math.abs(delta.y)>0) {
delta.setLocation((int)(delta.x*D), (int)(delta.y*D));
//Outside
if (vp.x<0 || vp.x+vport.getWidth()-label.getWidth()>0 ) delta.x = (int)(delta.x*D);
if (vp.y<0 || vp.y+vport.getHeight()-label.getHeight()>0) delta.y = (int)(delta.y*D);
} else {
inside.stop();
if (!isInside(vport, label)) outside.start();
}
}
});
this.outside = new javax.swing.Timer(20, new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
JViewport vport = (JViewport)label.getParent();
Point vp = vport.getViewPosition();
//System.out.format("r: %s\n", vp);
if (vp.x<0) vp.x = (int)(vp.x*D);
if (vp.y<0) vp.y = (int)(vp.y*D);
if (vp.x+vport.getWidth()-label.getWidth()>0)
vp.x = (int) (vp.x - (vp.x+vport.getWidth()-label.getWidth())*(1.0-D));
if (vp.y+vport.getHeight()>label.getHeight())
vp.y = (int) (vp.y - (vp.y+vport.getHeight()-label.getHeight())*(1.0-D));
vport.setViewPosition(vp);
if (isInside(vport, label)) outside.stop();
}
});
}
@Override public void mousePressed(MouseEvent e) {
label.setCursor(hc);
startPt.setLocation(e.getPoint());
inside.stop();
outside.stop();
}
@Override public void mouseDragged(MouseEvent e) {
Point pt = e.getPoint();
JViewport vport = (JViewport)label.getParent();
Point vp = vport.getViewPosition();
vp.translate(startPt.x-pt.x, startPt.y-pt.y);
vport.setViewPosition(vp);
delta.setLocation(SPEED*(pt.x-startPt.x), SPEED*(pt.y-startPt.y));
startPt.setLocation(pt);
}
@Override public void mouseReleased(MouseEvent e) {
label.setCursor(dc);
if (isInside((JViewport)label.getParent(), label)) {
inside.start();
} else {
outside.start();
}
}
}
解説
- scrollRectToVisible
- マウスを放したあと、タイマーを起動し、JComponent#scrollRectToVisible(Rectangle)メソッドでスクロール
- setViewPosition
- マウスを放したあと、タイマーを起動し、JViewport#setViewPosition(Point)メソッドでスクロール
- ViewであるJLabelの外で、移動が止まった(またはマウスがリリースされた)場合は、別のタイマーでJLabelの縁まで戻る
参考リンク
コメント
- 慣性(モーメンタム)スクロール、フリックスクロール(フリック+慣性スクロール?)、・・・でもやっぱり猫の掌スクロールを最初に思い出してしまう。 -- terai