在JavaFX和ScrollPanes中进行缩放

sar*_*can 7 javafx-2

我一直在尝试使用JavaFX中的缩放变换,但还没有完全绕过它.基本上,我有一个包含复杂图形的窗格,并希望能够重新缩放它.缩放部分本身工作正常,但是封闭的滚动窗格将不适应图形.

为简单起见,我将发布一个简短的示例,其中我的图形被标签替换:

public class TestApp extends Application {
    @Override public void start(final Stage stage) throws Exception {
        final Label label = new Label("Hello World");
        label.getTransforms().setAll(new Scale(0.5, 0.5));

        label.setStyle("-fx-background-color:blue");
        label.setFont(new Font(200));

        final ScrollPane scrollPane = new ScrollPane();
        scrollPane.setContent(label);

        stage.setScene(new Scene(scrollPane));
        stage.setWidth(200);
        stage.setHeight(100);
        stage.show();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
} 
Run Code Online (Sandbox Code Playgroud)

标签将正确缩放,但封闭的滚动窗格的条仍然可以容纳原始大小的组件.

我到目前为止尝试过:

  • 玩标签min和pref大小
  • 将标签包装在一个组内(不会出现任何滚动条)
  • 缩放封闭的组而不是标签

我错过了什么?如何使ScrollPane适应内容视图?

谢谢你的帮助.

Nun*_*ong 10

根据ScrollPane文档,您可能尝试将一个窗格包装在一个组中,以便ScrollPane按可视界限滚动而不是实际的布局边界.

ScrollPane layout calculations are based on the layoutBounds rather than the
boundsInParent (visual bounds) of the scroll node. If an application wants the
scrolling to be based on the visual bounds of the node (for scaled content etc.),
they need to wrap the scroll node in a Group. 
Run Code Online (Sandbox Code Playgroud)


jew*_*sea 4

在 JavaFX 中的滚动窗格视口、变换和布局边界示例中,我在 ScrollPane 中为图形和其他节点实现了缩放 。

该代码是在我第一次学习 JavaFX 时实现的,因此代码当然可以更简洁,并且也许有更简单的方法来实现此目的(例如,按照 ScrollPane 文档中的建议,使用 Group 作为缩放节点的容器

获得我想要的解决方案的一个关键(滚动条仅在放大并且节点大于可见视口时出现)是以下代码:

// create a container for the viewable node.
final StackPane nodeContainer = new StackPane();
nodeContainer.getChildren().add(node);

// place the container in the scrollpane and adjust the pane's viewports as required.
final ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(nodeContainer);
scrollPane.viewportBoundsProperty().addListener(
  new ChangeListener<Bounds>() {
  @Override public void changed(ObservableValue<? extends Bounds> observableValue, Bounds oldBounds, Bounds newBounds) {
    nodeContainer.setPrefSize(
      Math.max(node.getBoundsInParent().getMaxX(), newBounds.getWidth()),
      Math.max(node.getBoundsInParent().getMaxY(), newBounds.getHeight())
    );
  }
});

...

// adjust the view layout based on the node scalefactor.
final ToggleButton scale = new ToggleButton("Scale");
scale.setOnAction(new EventHandler<ActionEvent>() {
  @Override public void handle(ActionEvent actionEvent) {
    if (scale.isSelected()) {
      node.setScaleX(3); node.setScaleY(3);
    } else {
      node.setScaleX(1); node.setScaleY(1);
    }
    // runlater as we want to size the container after a layout pass has been performed on the scaled node.
    Platform.runLater(new Runnable() { 
      @Override public void run() {
        nodeContainer.setPrefSize(
          Math.max(nodeContainer.getBoundsInParent().getMaxX(), scrollPane.getViewportBounds().getWidth()),
          Math.max(nodeContainer.getBoundsInParent().getMaxY(), scrollPane.getViewportBounds().getHeight())
        );
      }
    });
  }
});
Run Code Online (Sandbox Code Playgroud)