8

我一直在尝试使用 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);
    }
} 

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

到目前为止我已经尝试过:

  • 使用标签 min 和 pref size
  • 将标签包装在组内(不会出现任何滚动条)
  • 缩放封闭组而不是标签

我错过了什么?我该怎么做才能使 ScrollPane 适应内容视图?

谢谢你的帮助。

4

2 回答 2

12

根据 ScrollPane 文档,您可能会尝试将 Pane 包装在 Group 中,因此 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. 
于 2013-07-13T13:18:38.843 回答
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())
        );
      }
    });
  }
});
于 2012-09-12T19:45:38.173 回答