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

自动调整画布的大小以填充封闭的父级

孟彦
2023-03-14

我最近想在JavaFX中创建一个动画背景,类似于这里看到的Swing示例。我使用画布进行绘制,如使用画布API中所示,并使用AnimationTimer进行绘制循环,如动画基础中所示。不幸的是,我不确定如何自动调整canvas的大小,因为封装的stage已经调整了大小。什么是好的方法?

在如何在JavaFX中使画布的大小可调整?中研究了类似的问题,但是这里的公认答案缺乏这里公认答案中所说明的绑定。

共有1个答案

彭华皓
2023-03-14

在下面的示例中,静态嵌套类canvaspanecanvas的实例包装在窗格中,并重写layoutchildrement()以使画布维度与封闭的窗格匹配。请注意,canvasisResizable()返回false,因此“父级不能在布局过程中调整它的大小”,而窗格“除了将可调整大小的子级调整到其首选大小之外,不会执行布局”。用于构造画布的宽度高度成为其初始大小。在集成粒子模拟Fireworks.java中也使用了类似的方法来缩放背景图像,同时保持其宽高比。

作为一个旁白,注意使用完全饱和的颜色与原来的不同。这些相关示例说明如何将控件置于动画背景之上。

import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

/**
 * @see https://stackoverflow.com/a/31761362/230513
 * @see https://stackoverflow.com/a/8616169/230513
 */

public class Baubles extends Application {

    private static final int MAX = 64;
    private static final double WIDTH = 640;
    private static final double HEIGHT = 480;
    private static final Random RND = new Random();
    private final Queue<Bauble> queue = new LinkedList<>();
    private Canvas canvas;

    @Override
    public void start(Stage stage) {
        CanvasPane canvasPane = new CanvasPane(WIDTH, HEIGHT);
        canvas = canvasPane.getCanvas();
        BorderPane root = new BorderPane(canvasPane);
        CheckBox cb = new CheckBox("Animate");
        cb.setSelected(true);
        root.setBottom(cb);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();

        for (int i = 0; i < MAX; i++) {
            queue.add(randomBauble());
        }
        AnimationTimer loop = new AnimationTimer() {
            @Override
            public void handle(long now) {
                GraphicsContext g = canvas.getGraphicsContext2D();
                g.setFill(Color.BLACK);
                g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
                for (Bauble b : queue) {
                    g.setFill(b.c);
                    g.fillOval(b.x, b.y, b.d, b.d);
                }
                queue.add(randomBauble());
                queue.remove();
            }
        };
        loop.start();
        cb.selectedProperty().addListener((Observable o) -> {
            if (cb.isSelected()) {
                loop.start();
            } else {
                loop.stop();
            }
        });
    }

    private static class Bauble {

        private final double x, y, d;
        private final Color c;

        public Bauble(double x, double y, double r, Color c) {
            this.x = x - r;
            this.y = y - r;
            this.d = 2 * r;
            this.c = c;
        }
    }

    private Bauble randomBauble() {
        double x = RND.nextDouble() * canvas.getWidth();
        double y = RND.nextDouble() * canvas.getHeight();
        double r = RND.nextDouble() * MAX + MAX / 2;
        Color c = Color.hsb(RND.nextDouble() * 360, 1, 1, 0.75);
        return new Bauble(x, y, r, c);
    }

    private static class CanvasPane extends Pane {

        private final Canvas canvas;

        public CanvasPane(double width, double height) {
            canvas = new Canvas(width, height);
            getChildren().add(canvas);
        }

        public Canvas getCanvas() {
            return canvas;
        }

        @Override
        protected void layoutChildren() {
            super.layoutChildren();
            final double x = snappedLeftInset();
            final double y = snappedTopInset();
            // Java 9 - snapSize is deprecated, use snapSizeX() and snapSizeY() accordingly
            final double w = snapSize(getWidth()) - x - snappedRightInset();
            final double h = snapSize(getHeight()) - y - snappedBottomInset();
            canvas.setLayoutX(x);
            canvas.setLayoutY(y);
            canvas.setWidth(w);
            canvas.setHeight(h);
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}
 类似资料:
  • 问题内容: 我需要将用户输入的文本显示为固定大小的div。我想要的是自动调整字体大小,以使文本尽可能多地填充框中。 所以-如果div为400px x 300px。如果有人输入ABC,那么它确实是大字体。如果他们输入一个段落,那么它将是很小的字体。 我可能想从最大字体大小开始-也许是32px,并且当文本太大而无法容纳容器时,请缩小字体大小直到适合为止。 问题答案: 和我的HTML是这样的 这是我的第

  • 问题内容: 我正在尝试使用Javafx制作屏幕键盘。我正在使用Scene Builder制作FXML文件。 但是,当调整窗口大小时,内容不会。我希望按钮增加/减小大小,直到适合窗口为止。启用Hgrow和Vgrow无效。 而且我找不到如何在按钮上设置填充。我想使类似Ctrl的按钮更小而不丢失文本。 问题答案: 根据字体大小调整大小 对于您的特定情况,而不是尝试使用填充或其他布局约束来调整按钮的大小,

  • 一直以来,我都在开发一款分辨率为800x480(流行手机分辨率)的应用程序。 我的画布HTML: 现在,为了使其全屏显示其他分辨率,我在调整大小事件后执行以下操作: 这是可行的,但问题是我不能以这种方式保持纵横比。800x480是4:3,但是如果我在5:3的手机上运行这个应用程序,有些东西(尤其是圆圈)看起来会被拉伸。 有没有什么方法可以让它在所有分辨率下看起来都很好,而不必为每个纵横比创建一组独

  • 问题内容: 如何自动缩放HTML5 元素以适合页面? 例如,我可以通过将和属性设置为100%来缩放,但是不会缩放吗? 问题答案: 我相信我已经找到了一个优雅的解决方案: JavaScript CSS 到目前为止,对我没有太大的负面性能影响。

  • 使用Java,我用GridBagLayout创建一个表单。GUI在一个J面板中,它在一个添加到JFrame的scrollPane中。 我希望带有GUI的JPanel的大小是固定的,以防止表单被拉伸,但是,我希望JScrollPanel可以根据用户的喜好调整大小。(类似于MS Paint,画布是我的JPanel)。我想要防止表单被拉伸的原因是因为我希望它能够打印,并且从我现在的方式来看,打印的表单几

  • 请看下面的P5代码 这个小应用程序的目的是在画布上拖放图像,根据“上传”图像的宽度和高度改变其大小。 使用:成功加载图像(至少显示图像)后,我将其宽度和高度分配给变量和。接着是画布大小的变化。。。这会导致一个错误,画布的大小与上传的图像相同(在上选中),但不显示任何内容。 使用:当禁用上的画布大小更改并单击画布时,调整大小会完美地显示图像。 应用程序需要在不点击的情况下工作,在删除图像后应该自动更