JPanelに表示した画像のズームとスクロール
Total: 9653
, Today: 1
, Yesterday: 2
Posted by aterai at
Last-modified:
概要
JPanel
に表示した画像にAffineTransform
による変換を適用して、マウスを使った拡大・縮小・移動を実行します。
Screenshot
Advertisement
サンプルコード
class ZoomAndPanHandler extends MouseAdapter {
private static final double ZOOM_FACTOR = 1.2;
private static final int MIN_ZOOM = -10;
private static final int MAX_ZOOM = 10;
private static final int EXTENT = 1;
private final BoundedRangeModel zoomRange = new DefaultBoundedRangeModel(
0, EXTENT, MIN_ZOOM, MAX_ZOOM + EXTENT);
private final AffineTransform coordAndZoomAtf = new AffineTransform();
private final Point2D dragStartPoint = new Point();
@Override public void mousePressed(MouseEvent e) {
dragStartPoint.setLocation(e.getPoint());
}
@Override public void mouseDragged(MouseEvent e) {
Point2D dragEndPoint = e.getPoint();
Point2D dragStart = transformPoint(dragStartPoint);
Point2D dragEnd = transformPoint(dragEndPoint);
coordAndZoomAtf.translate(
dragEnd.getX() - dragStart.getX(), dragEnd.getY() - dragStart.getY());
dragStartPoint.setLocation(dragEndPoint);
e.getComponent().repaint();
}
@Override public void mouseWheelMoved(MouseWheelEvent e) {
int dir = e.getWheelRotation();
int z = zoomRange.getValue();
zoomRange.setValue(z + EXTENT * (dir > 0 ? -1 : 1));
if (z != zoomRange.getValue()) {
double scale = dir > 0 ? 1d / ZOOM_FACTOR : ZOOM_FACTOR;
Point2D pt;
if (e.isControlDown()) {
Rectangle r = e.getComponent().getBounds();
pt = new Point2D.Double(r.getCenterX(), r.getCenterY());
} else {
pt = transformPoint(e.getPoint());
}
coordAndZoomAtf.translate(pt.getX(), pt.getY());
coordAndZoomAtf.scale(scale, scale);
coordAndZoomAtf.translate(-pt.getX(), -pt.getY());
e.getComponent().repaint();
}
}
// https://community.oracle.com/thread/1263955
// How to implement Zoom & Pan in Java using Graphics2D
private Point2D transformPoint(Point2D p1) {
AffineTransform inverse = coordAndZoomAtf;
boolean hasInverse = coordAndZoomAtf.getDeterminant() != 0d;
if (hasInverse) {
try {
inverse = coordAndZoomAtf.createInverse();
} catch (NoninvertibleTransformException ex) {
// should never happen
assert false;
}
}
Point2D p2 = new Point();
inverse.transform(p1, p2);
return p2;
}
public AffineTransform getCoordAndZoomTransform() {
return coordAndZoomAtf;
}
}
View in GitHub: Java, Kotlin解説
AffineTransform#createInverse()
で取得したAffineTransform
オブジェクトでマウス位置の逆変換を行い、現在表示されている倍率でのズームの中心や移動距離などを計算しています。
- ズーム
- ホイール上回転で拡大
- ホイール下回転で縮小
- スクロール
- マウスドラッグで移動
参考リンク
- How to implement Zoom & Pan in Java using Graphics2D
- ズームとパンの機能を備えたドローソフトを作成する:CodeZine
- 2000ピクセル以上のフリー写真素材集
- タッチ操作に対応した画像ビューワーをJavaScriptで作るならD3.jsが便利 - てっく煮ブログ
- CanvasでAffine変換で大いにはまる(数学的センスが足りなかった・・・) - torutkのブログ
- JScrollPane内に配置したJPanelをマウスで拡大、縮小、移動する
- Zooming at the Mouse Coordinates with Affine Transformations | by Ben Botto | Medium