In JavaFX if you want the user to be able to zoom the contents inside a scrollpane here’s a small gotcha that you have to be aware of: to accomplish this you must wrap the contents of the scroll node inside a group so that the visual bounds (not the layout bounds) are used for layout calculations.
Scrolling can than be attained by setting a scaling transform on the contents of the Scrollpane and adjusting the scale value to meet the specified zoom level.
Here’s a small snippet of code to illustrate how you could do it:
public class ZoomableScrollPane extends ScrollPane{ Group zoomGroup; Scale scaleTransform; Node content; (…) public ZoomableScrollPane(Node content) { this.content = content; Group contentGroup = new Group(); zoomGroup = new Group(); contentGroup.getChildren().add(zoomGroup); zoomGroup.getChildren().add(content); setContent(contentGroup); scaleTransform = new Scale(scaleValue, scaleValue, 0, 0); zoomGroup.getTransforms().add(scaleTransform); (…) } (…) }
Just be prepared for a massive performance drop (up to 100x) when zooming in your scroll pane with JavaFX 2.2 and earlier.
Got a shorter version:
imageView.setOnScroll(new EventHandler() {
@Override
public void handle(ScrollEvent event) {
event.consume();
if (event.getDeltaY() == 0) {
return;
}
double scaleFactor =
(event.getDeltaY() > 0)
? SCALE_DELTA
: 1 / SCALE_DELTA;
imageView.setScaleX(imageView.getScaleX() * scaleFactor);
imageView.setScaleY(imageView.getScaleY() * scaleFactor);
}
});
DoubleProperty zoomProperty = new SimpleDoubleProperty(200);
zoomProperty.addListener(new InvalidationListener() {
@Override
public void invalidated(Observable arg0) {
imageView.setFitWidth(zoomProperty.get() * 4);
imageView.setFitHeight(zoomProperty.get() * 3);
}
});
scrollPane.addEventFilter(ScrollEvent.ANY, new EventHandler() {
@Override
public void handle(ScrollEvent event) {
if (event.getDeltaY() > 0) {
zoomProperty.set(zoomProperty.get() * 1.1);
} else if (event.getDeltaY() < 0) {
zoomProperty.set(zoomProperty.get() / 1.1);
}
}
});
imageView.setImage(new Image("http://mikecann.co.uk/wp-content/uploads/2009/12/javafx_logo_color_1.jpg"));
scrollPane.setContent(imageView);
great! thank you
Brilliant! Saved me hours of digging and getting frustrated!
Thanks for the tip, it’s great.
The TabPane, however, seems to have a problem when placed inside such a zoomed and scrolled inner group:
http://stackoverflow.com/questions/35684271/javafx-tabpane-fails-to-render-when-inside-scrollpane-and-zoomed-group
how to set zoom event using keyboard for scrollpane..
There’s no zoom event. You have to catch mouse wheel events or keyboard events or whatever is your case and then zoom by adjusting the scale transform.