1
votes

I would like to show a photo as an ImageView in a ScrollPane with an ZoomIn and ZoomOut Function. But if I reduce by means of scale the imageview, an undesirable empty edge is created in the ScrollPane. How can you make sure that the ScrollPane is always the size of the scaled ImageView? See the following example. For simplicity, I replaced the ImageView with a rectangle.

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class ScrollPaneDemo extends Application {

    double scale;
    Pane contPane = new Pane();

    @Override
    public void start(Stage primaryStage) {
        BorderPane pane = new BorderPane();
        ScrollPane sp = new ScrollPane();
        sp.setContent(contPane);
        sp.setVvalue(0.5);
        sp.setHvalue(0.5);
        Rectangle rec = new Rectangle(2820, 1240,Color.RED);
        scale = 0.2;
        contPane.setScaleX(scale);
        contPane.setScaleY(scale);

        contPane.getChildren().add(rec);

        Button but1 = new Button("+");        
        but1.setOnAction((ActionEvent event) -> {
            scale*=2;
            contPane.setScaleX(scale);
            contPane.setScaleY(scale);
        });
        Button but2 = new Button("-");
        but2.setOnAction((ActionEvent event) -> {
            scale/=2;
            contPane.setScaleX(scale);
            contPane.setScaleY(scale);
        });
        HBox buttons = new HBox(but1, but2);
        pane.setTop(buttons);
        pane.setCenter(sp);
        Scene scene = new Scene(pane, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
1
try Adam Ren's answer hereTravisF

1 Answers

1
votes

contPane scaled by using transform don't change its layoutBounds automatically. If you want not to make empty space in contPane, you'd better wrap the node in Group.

See this post. Layout using the transformed bounds

sp.setContent(new Group(contPane));

In addition, if you don't want to make empty space in ScrollPane, limit minimum scale to rate which width or height of the content fits viewport's one.

Button but1 = new Button("+");
but1.setOnAction((ActionEvent event) -> {
    updateScale(scale * 2.0d);
});
Button but2 = new Button("-");
but2.setOnAction((ActionEvent event) -> {
    updateScale(scale / 2.0d);
});
HBox buttons = new HBox(but1, but2);
pane.setTop(buttons);
pane.setCenter(sp);
Scene scene = new Scene(pane, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();

updateScale(0.2d);

private void updateScale(double newScale) {
    scale = Math.max(newScale, Math.max(sp.getViewportBounds().getWidth() / rec.getWidth(), sp.getViewportBounds().getHeight() / rec.getHeight()));
    contPane.setScaleX(scale);
    contPane.setScaleY(scale);
}

Consider a case of the image is smaller than ScrollPane's viewport. Because for showing no empty space, this code will stretch contents when it doesn't have enough size.

In a case of huge images, TravisF's comment helps you.