studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones java animation javafx resize

java - programacion - Cambiar automáticamente el tamaño del lienzo para llenar el padre que lo encierra



manual de programacion android pdf (3)

¿No podrías hacer esto con un Binding también? Lo siguiente parece producir los mismos resultados sin tener que agregar la clase derivada.

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.beans.binding.DoubleBinding; 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.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) { canvas = new Canvas(WIDTH, HEIGHT); BorderPane root = new BorderPane(canvas); CheckBox cb = new CheckBox("Animate"); cb.setSelected(true); root.setBottom(cb); Scene scene = new Scene(root); stage.setScene(scene); stage.show(); // Create bindings for resizing. DoubleBinding heightBinding = root.heightProperty() .subtract(root.bottomProperty().getValue().getBoundsInParent().getHeight()); canvas.widthProperty().bind(root.widthProperty()); canvas.heightProperty().bind(heightBinding); 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); } public static void main(String[] args) { launch(args); } }

Hace poco quería crear un fondo animado en JavaFX, similar al ejemplo de Swing visto here . Usé un Canvas en el que dibujar, como se muestra en Trabajar con la API de Canvas , y un AnimationTimer de AnimationTimer para el bucle de dibujo, como se muestra en Conceptos básicos de animación . Desafortunadamente, no estoy seguro de cómo cambiar el tamaño del Canvas automáticamente a medida que se cambia el tamaño de la Stage adjunta. ¿Qué es un buen enfoque?

Una pregunta similar se examina en Cómo hacer que el lienzo sea redimensionable en javaFX? , pero la respuesta aceptada allí carece del enlace ilustrado en la respuesta aceptada here .


Combiné ambas soluciones anteriores (@trashgod y @ clataq''s) colocando el lienzo en un Panel y vinculándolo a él:

private static class CanvasPane extends Pane { final Canvas canvas; CanvasPane(double width, double height) { setWidth(width); setHeight(height); canvas = new Canvas(width, height); getChildren().add(canvas); canvas.widthProperty().bind(this.widthProperty()); canvas.heightProperty().bind(this.heightProperty()); } }


En el ejemplo a continuación, la clase estática anidada CanvasPane envuelve una instancia de Canvas en un Pane y anula layoutChildren() para hacer que las dimensiones del lienzo coincidan con el Pane circundante. Tenga en cuenta que Canvas devuelve false de isResizable() , por lo que "el padre no puede cambiar el tamaño durante el diseño" y el Pane "no realiza el diseño más allá de cambiar el tamaño de los niños redimensionables a sus tamaños preferidos". El width y la height utilizados para construir el lienzo se convierten en su tamaño inicial. Un enfoque similar se utiliza en la simulación de partículas Ensemble , Fireworks.java , para escalar una imagen de fondo mientras conserva su relación de aspecto.

Además, tenga en cuenta la diferencia de usar colores completamente saturados en comparación con el original. Estos examples relacionados ilustran la colocación de controles sobre el fondo animado.

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://.com/a/31761362/230513 * @see https://.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); } }