Swing/KineticScrolling のバックアップの現在との差分(No.5)
-
category: swing
folder: KineticScrolling
title: JScrollPaneでキネティックスクロール
tags: [JScrollPane, Animation, MouseListener, JViewport]
author: aterai
pubdate: 2010-08-16T13:34:26+09:00
description: JScrollPaneにキネティックスクロール(慣性スクロール)風の動作をするマウスリスナーを設定します。
image:
hreflang:
href: https://java-swing-tips.blogspot.com/2010/08/kinetic-scrolling-jscrollpane.html lang: en
概要
概要
JScrollPane
にキネティックスクロール(慣性スクロール)風の動作をするマウスリスナーを設定します。
Screenshot
Advertisement
サンプルコード
サンプルコード
#spandel
class KineticScrollingListener2 extends MouseAdapter {
#spanend
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);
#spanadd
class KineticScrollingListener2 extends MouseAdapter implements HierarchyListener {
#spanend
protected static final int SPEED = 4;
protected static final int DELAY = 10;
protected static final double D = .8;
protected final JComponent label;
protected final Point startPt = new Point();
protected final Point delta = new Point();
protected final Cursor dc;
protected final Cursor hc = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
protected final Timer inside = new Timer(DELAY, null);
protected final Timer outside = new Timer(DELAY, null);
#spanadd
#spanend
protected static boolean isInside(JViewport viewport, JComponent comp) {
Point vp = viewport.getViewPosition();
return vp.x >= 0 && vp.x + viewport.getWidth() - comp.getWidth() <= 0
&& vp.y >= 0 && vp.y + viewport.getHeight() - comp.getHeight() <= 0;
}
public KineticScrollingListener2(JComponent comp) {
#spanadd
#spanend
protected KineticScrollingListener2(JComponent comp) {
super();
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);
inside.addActionListener(e -> dragInside());
outside.addActionListener(e -> dragOutside());
}
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();
}
private void dragInside() {
JViewport viewport = (JViewport) SwingUtilities.getUnwrappedParent(label);
Point vp = viewport.getViewPosition();
// System.out.format("s: %s, %s%n", delta, vp);
vp.translate(-delta.x, -delta.y);
viewport.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 + viewport.getWidth() - label.getWidth() > 0) {
delta.x = (int) (delta.x * D);
}
});
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();
if (vp.y < 0 || vp.y + viewport.getHeight() - label.getHeight() > 0) {
delta.y = (int) (delta.y * D);
}
});
} else {
inside.stop();
if (!isInside(viewport, label)) {
outside.start();
}
}
}
#spanadd
#spanend
private void dragOutside() {
JViewport viewport = (JViewport) SwingUtilities.getUnwrappedParent(label);
Point vp = viewport.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 + viewport.getWidth() - label.getWidth() > 0) {
vp.x = (int) (vp.x - (vp.x + viewport.getWidth() - label.getWidth()) * (1d - D));
}
if (vp.y + viewport.getHeight() > label.getHeight()) {
vp.y = (int) (vp.y - (vp.y + viewport.getHeight() - label.getHeight()) * (1d - D));
}
viewport.setViewPosition(vp);
if (isInside(viewport, label)) {
outside.stop();
}
}
#spanadd
#spanend
@Override public void mousePressed(MouseEvent e) {
label.setCursor(hc);
e.getComponent().setCursor(hc);
startPt.setLocation(e.getPoint());
inside.stop();
outside.stop();
}
#spanadd
#spanend
@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));
JViewport viewport = (JViewport) SwingUtilities.getUnwrappedParent(label);
Point vp = viewport.getViewPosition();
vp.translate(startPt.x - pt.x, startPt.y - pt.y);
viewport.setViewPosition(vp);
delta.setLocation(SPEED * (pt.x - startPt.x), SPEED * (pt.y - startPt.y));
startPt.setLocation(pt);
}
#spanadd
#spanend
@Override public void mouseReleased(MouseEvent e) {
label.setCursor(dc);
if (isInside((JViewport)label.getParent(), label)) {
e.getComponent().setCursor(dc);
JViewport viewport = (JViewport) SwingUtilities.getUnwrappedParent(label);
if (isInside(viewport, label)) {
inside.start();
} else {
outside.start();
}
}
#spanadd
#spanend
@Override public void hierarchyChanged(HierarchyEvent e) {
Component c = e.getComponent();
if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0
&& !c.isDisplayable()) {
inside.stop();
outside.stop();
}
}
}
View in GitHub: Java, Kotlin解説
解説
scrollRectToVisible
- マウスを放したあと、タイマーを起動し、
JComponent#scrollRectToVisible(Rectangle)
メソッドでスクロール - マウスがリリースされたらタイマーを起動し、
JComponent#scrollRectToVisible(Rectangle)
メソッドでスクロール
- マウスを放したあと、タイマーを起動し、
setViewPosition
- マウスを放したあと、タイマーを起動し、
JViewport#setViewPosition(Point)
メソッドでスクロール -
View
であるJLabel
の外で、移動が止まった(またはマウスがリリースされた)場合は、別のタイマーでJLabel
の縁まで戻る - マウスがリリースされたらタイマーを起動し、
JViewport#setViewPosition(Point)
メソッドでスクロール -
View
として設定されているJLabel
の外で移動が止まった(またはマウスがリリースされた)場合は、別のタイマーでJLabel
の縁まで戻る
- マウスを放したあと、タイマーを起動し、