当前位置: 首页 > 知识库问答 >
问题:

JavaFX中带有layoutChildren()的AutoScalePane

易俊友
2023-03-14
public class Main extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("AutoScalePane Test");
        primaryStage.setScene(new Scene(root, 700, 200));
        primaryStage.show();
    }
}
public class Controller {
    @FXML
    public AutoScalePane scalePaneLeft;

    @FXML
    public AutoScalePane scalePaneRight;

    @FXML
    public void initialize() {
        fillLeftContent();
        fillRightContent();
    }

    private void fillLeftContent() {
        Circle circle1 = new Circle(100, 300, 10);
        Circle circle2 = new Circle(150, 300, 10);
        Circle circle3 = new Circle(200, 300, 10);
        Circle circle4 = new Circle(250, 300, 10);

        scalePaneLeft.addChildren(new Node[] {circle1, circle2, circle3,
                circle4});
    }

    private void fillRightContent() {
        Circle circle1 = new Circle(100, 200, 20);
        Circle circle2 = new Circle(150, 200, 20);
        Circle circle3 = new Circle(200, 200, 20);
        Circle circle4 = new Circle(250, 200, 20);

        scalePaneRight.addChildren(new Node[] {circle1, circle2, circle3,
                circle4});
    }
}

FXML视图:

<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import sample.AutoScalePane?>
<AnchorPane fx:controller="sample.Controller"
            xmlns:fx="http://javafx.com/fxml">


    <SplitPane dividerPositions="0.3" orientation="HORIZONTAL" AnchorPane.topAnchor="0" AnchorPane.bottomAnchor="0"
               AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" style="-fx-background-color: #2c5069;">

        <AutoScalePane fx:id="scalePaneLeft"
                       style="-fx-background-color: #943736;"/>

        <AutoScalePane fx:id="scalePaneRight"
                       style="-fx-background-color: #d27452;"/>

    </SplitPane>

</AnchorPane>

自动缩放窗格:

   /**
     * Auto-scales its content according to the available space of the Pane.
     * The content is always centered
     *
     */
    public class AutoScalePane extends Pane {

        private Group content = new Group();
        private Scale zoom = new Scale(1, 1);

        public AutoScalePane() {
            layoutBoundsProperty().addListener((o) -> {
                autoScale();
            });

            content.scaleXProperty().bind(zoom.xProperty());
            content.scaleYProperty().bind(zoom.yProperty());

            getChildren().add(content);
        }

        /**
         * Adds nodes to the AutoScalePane
         *
         * @param children nodes
         */
        public void addChildren(Node... children) {
            content.getChildren().addAll(children);
            requestLayout();
        }

        private void autoScale() {
            if (getHeight() > 0
                    && getWidth() > 0
                    && content.getBoundsInParent().getWidth() > 0
                    && content.getBoundsInParent().getHeight() > 0) {

                // scale
                double scaleX = getWidth() / content.getBoundsInParent().getWidth();
                double scaleY = getHeight() / content.getBoundsInParent()
                        .getHeight();

                System.out.println("*************** DEBUG ****************");
                System.out.println("Pane Width: " + getWidth());
                System.out.println("Content Bounds Width: " + content
                        .getBoundsInParent()
                        .getWidth());
                System.out.println("Pane Height: " + getHeight());
                System.out.println("Content Bounds Height: " + content
                        .getBoundsInParent()
                        .getHeight());
                System.out.println("ScaleX: " + scaleX);
                System.out.println("ScaleY: " + scaleY);

                double zoomFactor = Math.min(scaleX, scaleY);
                zoom.setX(zoomFactor);
                zoom.setY(zoomFactor);

                requestLayout();
            }
        }

        @Override
        protected void layoutChildren() {
            final double paneWidth = getWidth();
            final double paneHeight = getHeight();
            final double insetTop = getInsets().getTop();
            final double insetRight = getInsets().getRight();
            final double insetLeft = getInsets().getLeft();
            final double insertBottom = getInsets().getBottom();

            final double contentWidth = (paneWidth - insetLeft - insetRight) *
                    zoom.getX();
            final double contentHeight = (paneHeight - insetTop - insertBottom) *
                    zoom.getY();

            layoutInArea(content, 0, 0, contentWidth, contentHeight,
                    getBaselineOffset(), HPos.CENTER, VPos.CENTER);
        }
    }

共有1个答案

李烨
2023-03-14

在更改节点大小时调用layoutchildren。如果从LayoutChildren方法调整小数位数,则不需要注册侦听器。

至于缩放:您从未真正修改scale属性。除了以下代码段之外,您不能在任何地方更新刻度

double zoomFactor = Math.min(zoom.getX(), zoom.getY());
zoom.setX(zoomFactor);
zoom.setY(zoomFactor);

因此zoom.getx()zoom.gety()始终返回等于初始比例因子的1

public class AutoScalePane extends Region {

    private final Group content = new Group();

    public AutoScalePane() {
        content.setManaged(false); // avoid constraining the size by content
        getChildren().add(content);
    }

    /**
     * Adds nodes to the AutoScalePane
     *
     * @param children nodes
     */
    public void addChildren(Node... children) {
        content.getChildren().addAll(children);
        requestLayout();
    }

    @Override
    protected void layoutChildren() {
        final Bounds groupBounds = content.getBoundsInLocal();

        final double paneWidth = getWidth();
        final double paneHeight = getHeight();
        final double insetTop = getInsets().getTop();
        final double insetRight = getInsets().getRight();
        final double insetLeft = getInsets().getLeft();
        final double insertBottom = getInsets().getBottom();

        final double contentWidth = (paneWidth - insetLeft - insetRight);
        final double contentHeight = (paneHeight - insetTop - insertBottom);

        // zoom
        double factorX = contentWidth / groupBounds.getWidth();
        double factorY = contentHeight / groupBounds.getHeight();
        double factor = Math.min(factorX, factorY);
        content.setScaleX(factor);
        content.setScaleY(factor);

        layoutInArea(content, insetLeft, insetTop, contentWidth, contentHeight,
                getBaselineOffset(), HPos.CENTER, VPos.CENTER);
    }

}
 类似资料:
  • 我必须在JavaFX中做一些用画布绘制正多边形的项目,我对如何使用GraphicsContext用画布设计一个圆有疑问 在主JavaFX中

  • 我有一个使用flowless项目的JavaFX列表。但是我得到了一个奇怪的边框(我没有启用任何边框,并且强制边框具有width=0px),它存在并且具有渐变效果: 当我将单元格background-inset设置为-1时,边框就没有了,所以我相信这个问题与背景有关。虽然这不是一个解决方案,因为如果我启用了边框(这是我想要的),渐变效果仍然存在。 有人知道我怎样才能摆脱这个边界吗? 谢谢!

  • 我在我的javafx应用程序中使用锚板。我想画一个矩形并用渐变色填充它,如下所示:矩形的左侧是蓝色的,右侧是红色的,我希望它看起来从左到右,蓝色减少,红色增加。 我知道如何放置一个矩形(如何在javafx中使用Rectangle类),但我不知道如何以这种方式填充它。有什么想法吗?

  • 我得到了 fxml_example.fxml FXMLExAmple.java

  • 我想绑定JavaFX与值。 我试过了,例如。 或 但我总是得到NullPointerException。 我怎么才能修好它?

  • 我有一个多模块maven项目,我对javaFx有问题(我使用了zenJava插件)。 当我想要构建jar时,我有一个错误:无法执行目标com。zenjava:javafx maven插件:8.8.3:在项目XXXX上构建jar(默认cli):目标com的参数“mainClass”。zenjava:javafx maven插件:8.8.3:build jar缺失或无效 但是,我在父pom中定义了ma