JavaFX ScrollPane и масштабирование содержимого

Я хотел бы показать фотографию как ImageView в ScrollPane с функцией ZoomIn и ZoomOut. Но если я уменьшаю масштаб изображения, в ScrollPane создается нежелательный пустой край. Как убедиться, что ScrollPane всегда соответствует размеру масштабированного изображения? См. следующий пример. Для простоты я заменил ImageView прямоугольником.

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

person user1878143    schedule 27.04.2017    source источник
comment
попробуйте ответить Адама Рена здесь   -  person TravisF    schedule 28.04.2017


Ответы (1)


contPane масштабируется с помощью преобразования, не изменяет его layoutBounds автоматически. Если вы хотите, чтобы в contPane не было пустого места, лучше оберните узел в Group.

Смотрите этот пост. Макет с использованием преобразованных границ

sp.setContent(new Group(contPane));

Кроме того, если вы не хотите создавать пустое пространство в панели прокрутки, ограничьте минимальный масштаб, чтобы указать, какая ширина или высота содержимого соответствует ширине окна просмотра.

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

Рассмотрим случай, когда изображение меньше окна просмотра ScrollPane. Поскольку для отображения отсутствия пустого места этот код будет растягивать содержимое, когда ему не хватает размера.

В случае огромных изображений вам поможет комментарий TravisF.

person monolith52    schedule 28.04.2017
comment
Бокс с группой помогает. Спасибо. - person user1878143; 29.04.2017
comment
У меня была та же проблема, и упаковка с группой помогла увеличить масштаб, но если у группы много дочерних узлов, то рендеринг ScrollPane станет медленнее. - person Muhammad Ali; 09.09.2020