I'm having trouble scaling components inside of the anchor pane relating to the size of the anchor pane.
What I want to achieve is a rectangle 50% x 50% the size of the anchor pane positioned at the center.

我目前正在try 使用以下代码来实现这一点:

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

但是,我没有显示任何矩形.

我想知道是否有解决这种方法的方法,或者是否有更好的方法来zoom 面板中的 node ,我应该try 一下.

推荐答案

您的代码无法运行的原因有两个:

  1. Rectangle个(以及所有Shape个)实例不是resizable个.这意味着父 node (例如AnchorPane)不能调整这些 node 的大小(具体地说,Rectangle.resize()是无操作的).
  2. 您正在拨打centerPane.getHeight(),而面板还没有布置好.这意味着届时其height(和width)将为零.当宽度和高度改变时,你真的需要重新做布局.

JavaFX支持Pane个子类的集合,这些子类管理布局.(例如,请参见this tutorialAPI docs)以了解详细信息.)通常,如果您需要的布局策略不受这些布局窗格之一的支持,则您应该通过将RegionPane子类化来定义您自己的布局策略.您至少应该覆盖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();
    }
}

以下是一个快速测试 case :

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

enter image description here

Java相关问答推荐

Selenium Java:无法访问IFRAME内部的元素

Kubernetes的Java客户端检索状态.处于终止状态的Pod的阶段';正在运行';

Hibernate 6支持Joda DateTime吗?

R.id.main给我一个红色错误,无法解析MainActivity.java中的符号main

我正在try 跟踪数组中最大的两个数字

JDK 21-为什么线程局部随机S nextInt不直接用Super.nextInt实现?

从ActiveMQ Classic迁移到ActiveMQ Artemis需要进行哪些客户端更改?

用OSQL创建索引

尽管通过中断请求线程死亡,但线程仍将继续存在

有效的公式或值列表必须少于或等于255个字符

从LineChart<;字符串、字符串和gt;中删除数据时出现特殊的ClassCastException;

泛型与泛型问题的完美解决方案?

为什么mvn编译生命周期阶段不只是编译已更改的java文件?

如何在ApacheHttpClient 5中为单个请求设置代理?

通过/失败的参数化junit测试方法执行数

为什么没有加载java.se模块?

我们可以在方法中声明接口吗?

如何使用带有可选参数的类生成器?

ResponseEntity.控制器截断响应的JSON部分

Swagger.io OpenApi v3.0 声明默认媒体类型