我以ScrollPane为根。此ScrollPane包含三个ZoomableCanvas。当我尝试通过鼠标滚动缩放Canvas时,ScrollPane也在滚动。那么解决这个问题的方法是什么?
我的ZoomableCanvas覆盖MouseScrollEvent来缩放画布的图片
public abstract class ZoomableCanvas extends Canvas {
private class DragContext {
double mouseAnchorX;
double mouseAnchorY;
double translateAnchorX;
double translateAnchorY;
double finalPositionX;
double finalPositionY;
double mouseXPos;
double mouseYPos;
}
private DragContext sceneDragContext;
private SimpleDoubleProperty zoom = new SimpleDoubleProperty(1.0);
public ZoomableCanvas() {
this(0, 0);
}
public ZoomableCanvas(double width, double height) {
super(width, height);
this.getStyleClass().add("visualisation-container");
sceneDragContext = new DragContext();
this.setOnScroll(zoomHandler);
this.setOnMouseMoved(event -> {
sceneDragContext.mouseXPos = event.getX();
sceneDragContext.mouseYPos = event.getY();
});
this.setOnMousePressed(event -> {
ZoomableCanvas canvas = (ZoomableCanvas) event.getSource();
// right mouse button => panning
if( !event.isPrimaryButtonDown())
return;
sceneDragContext.mouseAnchorX = event.getX();
sceneDragContext.mouseAnchorY = event.getY();
Affine transform = canvas.getGraphicsContext2D().getTransform();
sceneDragContext.translateAnchorX = transform.getTx();
sceneDragContext.translateAnchorY = transform.getTy();;
event.consume();
});
this.setOnMouseDragged(event -> {
if( !event.isPrimaryButtonDown())
return;
sceneDragContext.finalPositionX = event.getX();
sceneDragContext.finalPositionY = event.getY();
redraw(false);
event.consume();
});
this.zoomProperty().addListener(o -> redraw(true));
}
static protected EventHandler<ScrollEvent> zoomHandler = new EventHandler<ScrollEvent>() {
@Override
public void handle(ScrollEvent event) {
ZoomableCanvas zcanvas = (ZoomableCanvas) event.getSource();
GraphicsContext gc = zcanvas.getGraphicsContext2D();
Affine affine = gc.getTransform();
double zoom = affine.getMxx() + event.getDeltaY() / 800;
if(zoom <= 0) zoom = 0;
zcanvas.setZoom(zoom);
zcanvas.redraw(true);
}
};
public void setZoom(double value) {
if (value != getZoom()) {
this.zoom.set(value);
redraw(true);
}
}
public double getZoom() {
return zoom.get();
}
public DoubleProperty zoomProperty() {
return zoom;
}
public void clean() {
GraphicsContext gc = this.getGraphicsContext2D();
Canvas canvas = gc.getCanvas();
Affine affine = gc.getTransform();
gc.setTransform(1, 0, 0, 1, 0, 0);
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
gc.setTransform(affine);
}
private void redraw(boolean zoom) {
GraphicsContext gc = this.getGraphicsContext2D();
if (gc == null) return;
// Clear:
Canvas canvas = gc.getCanvas();
double w = canvas.getWidth();
double h = canvas.getHeight();
gc.setTransform(1, 0, 0, 1, 0, 0);
gc.clearRect(0, 0, w, h);
double z = getZoom();
if(zoom)
gc.setTransform(z, 0, 0, z, (sceneDragContext.mouseXPos - sceneDragContext.mouseXPos * z)/2, (sceneDragContext.mouseYPos - sceneDragContext.mouseYPos * z)/2);
else
gc.setTransform(z, 0, 0, z, sceneDragContext.translateAnchorX + sceneDragContext.finalPositionX - sceneDragContext.mouseAnchorX, sceneDragContext.translateAnchorY + sceneDragContext.finalPositionY - sceneDragContext.mouseAnchorY);
paint(gc);
}
public abstract void paint(GraphicsContext gc);
}
这是我的演示,以显示缩放
public class ZoomAndScrollApplication extends Application {
public static void main(String[] args) {
launch(args);
}
private void draw(GraphicsContext gc) {
gc.setFill(Color.LIGHTGREEN);
gc.fillOval(60, 10, 180, 180);
gc.setFill(Color.WHITE);
gc.fillOval(100, 50, 100, 100);
}
@Override
public void start(Stage stage) throws Exception {
ZoomableCanvas zoomableCanvas1 = new ZoomableCanvas(300, 400) {
@Override
public void paint(GraphicsContext gc) {
draw(gc);
}
};
draw(zoomableCanvas1.getGraphicsContext2D());
ZoomableCanvas zoomableCanvas2 = new ZoomableCanvas(300, 400) {
@Override
public void paint(GraphicsContext gc) {
draw(gc);
}
};
draw(zoomableCanvas2.getGraphicsContext2D());
ZoomableCanvas zoomableCanvas3 = new ZoomableCanvas(300, 400) {
@Override
public void paint(GraphicsContext gc) {
draw(gc);
}
};
draw(zoomableCanvas3.getGraphicsContext2D());
VBox canvasContainer = new VBox(zoomableCanvas1, zoomableCanvas2, zoomableCanvas3);
ScrollPane root = new ScrollPane(canvasContainer);
Scene scene = new Scene(root, 1024, 768);
stage.setScene(scene);
stage.show();
}
}