JavaFX AnchorPane 缩放

问题描述 投票:0回答:1

我在缩放与锚定窗格大小相关的锚定窗格内的组件时遇到问题。
我想要实现的是一个矩形,其大小为位于中心的锚定窗格的 50% x 50%。

我目前正在尝试使用此代码来实现此目的:

public class HelloApplication extends Application {

    @Override
    public void start(Stage stage) throws IOException {
        AnchorPane centerPane = new AnchorPane();

        Rectangle rect = new Rectangle();
        rect.setFill(Color.BLUE);

        AnchorPane.setTopAnchor(rect, .25 * centerPane.getHeight());
        AnchorPane.setBottomAnchor(rect, .25 * centerPane.getHeight());
        AnchorPane.setLeftAnchor(rect, .25 * centerPane.getHeight());
        AnchorPane.setRightAnchor(rect, .25 * centerPane.getHeight());

        Scene scene = new Scene(centerPane, 320, 240);

        stage.setTitle("Anchor Pane Scaling test");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
    
}

但是我没有显示矩形。

我想知道是否有办法解决这种方法,或者是否有更好的方法来缩放窗格内的节点,我应该尝试。

java user-interface javafx scaling
1个回答
1
投票

您的代码不起作用有两个原因:

  1. Rectangle
    (以及所有
    Shape
    )实例是 非托管。这意味着父节点(例如
    AnchorPane
    )不会调整这些节点的大小或重新定位这些节点。
  2. 您在布局窗格之前调用
    centerPane.getHeight()
    。这意味着此时它的
    height
    (和
    width
    )将为零。每当宽度和高度发生变化时,您确实需要重新进行布局。

JavaFX 支持一组管理布局的

Pane
子类。 (例如,请参阅本教程API文档)了解详细信息。)通常,如果您需要这些布局窗格之一不支持的布局策略,那么您应该通过子类化来定义自己的布局策略
 Region
Pane
。您至少应该重写
layoutChildren()
方法以及计算最小/首选/最大宽度和高度的方法。

从您的问题中尚不清楚您的实际用例是否保证执行此操作所需的编码量。但是,这里是一个容器窗格的简单示例,该窗格将其内容居中并具有可配置值,用于确定其内容应占据其大小的(线性)比例。

package org.jamesd.examples.centeringpane;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.layout.Region;

public class CenteringPane extends Region {

    private final Node content ;
    private DoubleProperty sizeProportion = new SimpleDoubleProperty(1);

    public CenteringPane(Node content) {
        this.content = content;
        getChildren().add(content);
        sizeProportion.addListener(obs -> requestLayout());
    }

    @Override
    protected void layoutChildren() {
        if (content.isManaged()) {
            double w = getWidth();
            double h = getHeight();
            double targetWidth = (w - snappedLeftInset() - snappedRightInset()) * getSizeProportion();
            double targetHeight = (h - snappedTopInset() - snappedBottomInset()) * getSizeProportion();
            double x = (w - targetWidth) / 2;
            double y = (h - targetHeight) / 2;
            content.resizeRelocate(snapPositionX(x), snapPositionY(y), snapSizeX(targetWidth), snapSizeY(targetHeight));
        }
    }

    public double getSizeProportion() {
        return sizeProportion.get();
    }

    public DoubleProperty sizeProportionProperty() {
        return sizeProportion;
    }

    public void setSizeProportion(double sizeProportion) {
        this.sizeProportion.set(sizeProportion);
    }

    @Override
    protected double computePrefWidth(double height) {
        return snappedLeftInset() + snappedRightInset() + content.prefWidth(height) / getSizeProportion();
    }

    @Override
    protected double computePrefHeight(double width) {
        return snappedTopInset() + snappedBottomInset() + content.prefHeight(width) / getSizeProportion();
    }

    @Override
    protected double computeMinWidth(double height) {
        return snappedLeftInset() + snappedRightInset() + content.minWidth(height) / getSizeProportion();
    }

    @Override
    protected double computeMinHeight(double width) {
        return snappedTopInset() + snappedBottomInset() + content.minHeight(width) / getSizeProportion();
    }

    @Override
    protected double computeMaxWidth(double height) {
        return snappedLeftInset() + snappedRightInset() + content.maxWidth(height) / getSizeProportion();
    }

    @Override
    protected double computeMaxHeight(double width) {
        return snappedTopInset() + snappedBottomInset() + content.maxHeight(width) / getSizeProportion();
    }

    @Override
    public Orientation getContentBias() {
        return content.getContentBias();
    }
}

这是一个快速测试用例:

package org.jamesd.examples.centeringpane;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.Background;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) {
        Pane pane = new Pane();
        pane.setBackground(Background.fill(Color.BLUE));
        CenteringPane centeringPane = new CenteringPane(pane);

        BorderPane root = new BorderPane(centeringPane);
        Slider slider = new Slider(0, 1, 0.5);

        centeringPane.sizeProportionProperty().bind(slider.valueProperty());
        HBox controls = new HBox(5, slider);
        controls.setPadding(new Insets(10));
        controls.setAlignment(Pos.CENTER);
        root.setTop(controls);
        Scene scene = new Scene(root, 800, 500);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.