自动调整画布,以填补封装的父 [英] Automatically resize Canvas to fill the enclosing Parent

查看:272
本文介绍了自动调整画布,以填补封装的父的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近想创建JavaFX中动画背景,类似于这里看到 Swing的例子。我用了一个 帆布 上绘制,如图的与画布API ,和的 AnimationTimer 为绘图循环,如的 动画基础 的。不幸的是,我不知道如何来调整画布自动封闭舞台调整大小。什么是好办法?

I recently wanted to create an animated background in JavaFX, similar to the Swing example seen here. I used a Canvas on which to draw, as shown in Working with the Canvas API, and an AnimationTimer for the drawing loop, as shown in Animation Basics. Unfortunately, I'm not sure how to resize the Canvas automatically as the enclosing Stage is resized. What is a good approach?

推荐答案

在下面的例子中,Static Nested Class和 CanvasPane 包装的 画布 面板 并覆盖 layoutChildren()来使画布尺寸封装匹配面板 。需要注意的是画布收益来自的 isResizable() ,所以家长不能调整它的布局中,与面板不执行超出调整可调整大小的孩子他们的preferred尺寸的布局。在宽度高度用于构造画布成为其初始大小。类似的方法在乐团 粒子模拟,<一个href=\"http://grep$c$c.com/file/repo1.maven.org/maven2/org.jbundle.javafx.example/org.jbundle.javafx.example.ensemble/0.9.0/ensemble/samples/canvas/FireworksSample.java#FireworksSample.SanFranciscoFireworks.layoutChildren%28%29\"相对=nofollow> Fireworks.java ,缩放背景图像,同时保留其长宽比。

In the example below, the static nested class CanvasPane wraps an instance of Canvas in a Pane and overrides layoutChildren() to make the canvas dimensions match the enclosing Pane. Note that Canvas returns false from isResizable(), so "the parent cannot resize it during layout," and Pane "does not perform layout beyond resizing resizable children to their preferred sizes." The width and height used to construct the canvas become its initial size. A similar approach is used in the Ensemble particle simulation, Fireworks.java, to scale a background image while retaining its aspect ratio.

顺便说一句,使用完全饱和的颜色比原来的注意区别。

As an aside, note the difference from using fully saturated colors compared to the original.

图像

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 http://stackoverflow.com/a/31761362/230513
 * @see http://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() {
            final double x = snappedLeftInset();
            final double y = snappedTopInset();
            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);
    }
}

这篇关于自动调整画布,以填补封装的父的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆