gpt4 book ai didi

java - 自动调整 Canvas 大小以填充封闭的父级

转载 作者:搜寻专家 更新时间:2023-10-30 19:57:45 24 4
gpt4 key购买 nike

我最近想在 JavaFX 中创建一个动画背景,类似于看到的 Swing 示例 here .我用了 Canvas在其上绘制,如 Working with the Canvas API 所示, 和一个 AnimationTimer对于绘图循环,如 Animation Basics 所示.不幸的是,我不确定如何在调整封闭的 Stage 大小时自动调整 Canvas 的大小。什么是好的方法?

image

How to make canvas Resizable in javaFX? 中检查了类似的问题,但接受的答案缺少接受的答案中说明的绑定(bind) here .

最佳答案

在下面的示例中,静态嵌套类 CanvasPane 包装了 Canvas 的一个实例在Pane并覆盖 layoutChildren() 以使 Canvas 尺寸与封闭的 Pane 匹配。请注意,CanvasisResizable() 返回 false ,所以“父级不能在布局期间调整它的大小”,并且 Pane“除了将可调整大小的子级调整到他们喜欢的尺寸之外不执行布局。”用于构造 Canvas 的 widthheight 成为其初始大小。 Ensemble 中使用了类似的方法粒子模拟,FireworksApp , 在保持纵横比不变的情况下缩放背景图像。

顺便说一句,请注意使用完全饱和的颜色与原始颜色的区别。这些相关examples说明将控件放置在动画背景之上。

image

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

关于java - 自动调整 Canvas 大小以填充封闭的父级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31761361/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com