Recentemente ho voluto creare uno sfondo animato in JavaFX, simile all'esempio Swing visto here. Ho utilizzato uno Canvas
su cui disegnare, come mostrato in Working with the Canvas API e uno AnimationTimer
per il ciclo di disegno, come mostrato in Animation Basics. Sfortunatamente, non sono sicuro di come ridimensionare lo Canvas
automaticamente quando viene ridimensionato lo Stage
che si sta chiudendo. Qual è un buon approccio?Ridimensiona automaticamente la tela per riempire la Parent Parent allegata
risposta
Nell'esempio seguente, la classe innestata statica CanvasPane
avvolge un'istanza di Canvas
in un Pane
e sovrascrive layoutChildren()
per rendere le tela dimensioni corrispondono alla racchiude Pane
. Si noti che Canvas
restituisce da isResizable()
, quindi "il genitore non può ridimensionarlo durante il layout" e Pane
"non esegue il layout oltre il ridimensionamento dei bambini ridimensionabili alle dimensioni preferite." Il width
e height
utilizzati per costruire la tela diventano la sua dimensione iniziale. Un approccio simile viene utilizzato nella simulazione delle particelle Ensemble, Fireworks.java
, per ridimensionare un'immagine di sfondo mantenendo il suo rapporto aspetto.
Come nota a parte, notare la differenza dall'utilizzo di colori completamente saturi rispetto all'originale. Questi numeri correlati examples illustrano i controlli di posizionamento in cima allo sfondo animato.
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();
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);
}
}
Non potresti farlo con un Binding
come bene? Quanto segue sembra produrre gli stessi risultati senza dover aggiungere la classe derivata.
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);
}
}
Grazie per aver suggerito 'Binding'. Sono corretto dedurre che l'associazione dovrebbe cambiare per un diverso layout 'root'? Ho provato solo 'CanvasPane' in' BorderPane' e 'StackPane'. – trashgod
I dettagli dovrebbero cambiare, ma qualcosa di simile dovrebbe funzionare. Inoltre, l'esempio non è perfettamente generale per un 'BorderPane' poiché alcuni dettagli dovrebbero essere modificati se si hanno nodi nelle posizioni superiore, sinistra o destra. – clartaq
Ah, capisco; in uno 'StackPane', potrei' legare() '' canvas.heightProperty() 'direttamente a' root.heightProperty() '. Fino ad ora penso che 'CanvasPane' sia più flessibile, ma più uno per un'alternativa utile e un esempio concreto di aritmetica' Binding'. – trashgod
- 1. Breve mano per .parent(). Parent(). Parent()
- 2. Modo più pulito per scrivere element.parent(). Parent(). Parent(). Parent(). Parent()
- 3. Stirazzi per riempire la tela
- 4. jQuery ottiene parent parent per questo solo elemento
- 5. UIPopovercontroller Parent?
- 6. PHP Codeigniter - parent :: __ construct
- 7. Che è più efficiente: .parent(). Parent(). Parent() ~ o ~ parents (". Foo") ~ or ~ closest (". Foo")
- 8. modulo Parent come dipendenza
- 9. Utilizzo $ this, self ::, parent :: per la leggibilità del codice
- 10. Access Parent Repeaters DataItem Property
- 11. Comunicazione fork parent genitore
- 12. Bash find, exclude parent?
- 13. Parent(), alternativa più veloce?
- 14. CSS Parent/Ancestor Selettore
- 15. Perché PHP non chiama automaticamente i costruttori parent?
- 16. jQuery .parent() non funziona
- 17. jscrollpane block scrolling parent
- 18. Hibernate: Save Parent automaticamente prima di risparmio del bambino
- 19. Ridimensiona la tela attorno a una bitmap?
- 20. Ridimensiona la tela con fabric js
- 21. CSS Fill parent div 100% clean
- 22. CSS child clearing parent float
- 23. Accesso Namespace Parent in C++
- 24. Reagire Native Parent Bambino comunicazione
- 25. jQuery parent di un genitore
- 26. sostituisce la versione della libreria definita in parent pom
- 27. Super init vs. parent .__ init__
- 28. angularJS: Come chiamare la funzione scope child nello scope parent
- 29. ricorsiva concatenazione di Parent Elementi
- 30. $ ("# dialog"). Parent(). AppendTo ($ ("form: first"));
Nice demo .. + 1 .. – Reimeus