Zooming inside a Scrollpane

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);
    (…)
  }
  (…)
}
About these ads

6 thoughts on “Zooming inside a Scrollpane

  1. JavaPins

  2. Java desktop links of the week, September 30 | Jonathan Giles

  3. JavaFX links of the week, September 30 // JavaFX News, Demos and Insight // FX Experience

  4. 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);
    }
    });

  5. 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&quot;));
    scrollPane.setContent(imageView);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s