Swing でズーム可能なマップを作成しようとしています。マップは JScrollPane 内の JPanel です。ズームインすると、マップのサイズが変わり、paint() によって要素が別の位置にペイントされます。これはすべてうまくいきます。
ただし、ScrollPane は画像サイズを大きくしてもビューポートを変更しなかったため、ズームインすると常に、見ている要素が画面外に移動しました。でこれを解決しようとしましscrollRectToVisible()
たが、ジオメトリの実行に失敗したか、Swing をよく理解していないために、長方形の正しい座標を取得できませんでした。
ここに私が持っているものがあります:
public class MapPanel extends JPanel {
[...]
public void setZoom(double zoom) {
// get the current viewport rectangle and its center in the scaled coordinate system
JViewport vp = (JViewport) this.getParent();
Rectangle rect = vp.getViewRect();
Point middle = getMiddle(rect);
Dimension dim = rect.getSize();
// zoom in
scaler.setZoom(zoom);
setPreferredSize(scaler.transform(dim));
this.revalidate();
// calculate the full size of the scaled coordinate system
Dimension fullDim = scaler.transform(dim);
// calculate the non-scaled center of the viewport
Point nMiddle = new Point((int) ((double) (middle.x)/fullDim.width*dim.width),(int) ((double) (middle.y)/fullDim.height*dim.height));
// this should do the trick, but is always a bit off towards the origin
scrollRectToVisible(getRectangleAroundPoint(nMiddle));
// the below alternative always zooms in perfectly to the center of the map
// scrollRectToVisible(getRectangleAroundPoint(new Point(400,300)));
}
private Rectangle getRectangleAroundPoint(Point p){
Point newP = scaler.transform(p);
Dimension d = railMap.getDimension();
Point corner = new Point(newP.x-d.width/2,newP.y-d.height/2);
return new Rectangle(corner,d);
}
private Point getMiddle(Rectangle r){
return new Point(r.x+r.width/2,r.y+r.height/2);
}
}
そして、これが Scaler クラスです (これは特に驚くようなことはしていないと思います):
public class Scaler {
private double zoom = 1;
public void setZoom(double zoom) {
this.zoom = zoom;
}
public Point transform(Point2D p){
return new Point((int) (p.getX()*zoom), (int) (p.getY()*zoom));
}
public Dimension transform(Dimension d){
return new Dimension((int) (d.width*zoom), (int) (d.height*zoom));
}
}
どこで問題が発生しているのか誰が教えてくれますか? マップの現在の中心の有効な計算を行ったように思えますが、ズームポイントを固定するとうまくいきます...
編集:ここで難しいのは、古いビューポートの四角形に基づいて新しいビューポートの四角形を作成することです。