对于我的Java课程,我必须创建一个基于网格的动画。基本上我目前有一个包含某些值的二维数组,每次运行程序时都会更改。例如,它可以是20x20 2d阵列,或32x32等。在阵列内部存储某些值,字符代表动物,数字代表食物。动物闻到食物然后在程序的每个循环后移向食物,因此它们在阵列中的位置在每个循环后改变。该计划的运作方式与我提出的问题无关。
基本上我现在必须在JavaFX中实现它(它目前在控制台中工作,每个周期将数组显示为网格)。我只是想知道哪种控件最适合在JavaFX中使用以显示二维数组,或者是否有人可以指出我如何开始编码的正确方向?
我是java(和JavaFX)的新手,所以我不确定要使用哪些控件......
答案 0 :(得分:4)
我不会使用控件。我宁愿为数组中的每个项创建一个节点,并将它们放在场景中。像这样:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class NodeDemo extends Application {
private double sceneWidth = 1024;
private double sceneHeight = 768;
private int n = 10;
private int m = 10;
double gridWidth = sceneWidth / n;
double gridHeight = sceneHeight / m;
MyNode[][] playfield = new MyNode[n][m];
@Override
public void start(Stage primaryStage) {
Group root = new Group();
// initialize playfield
for( int i=0; i < n; i++) {
for( int j=0; j < m; j++) {
// create node
MyNode node = new MyNode( "Item " + i + "/" + j, i * gridWidth, j * gridHeight, gridWidth, gridHeight);
// add node to group
root.getChildren().add( node);
// add to playfield for further reference using an array
playfield[i][j] = node;
}
}
Scene scene = new Scene( root, sceneWidth, sceneHeight);
primaryStage.setScene( scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public static class MyNode extends StackPane {
public MyNode( String name, double x, double y, double width, double height) {
// create rectangle
Rectangle rectangle = new Rectangle( width, height);
rectangle.setStroke(Color.BLACK);
rectangle.setFill(Color.LIGHTBLUE);
// create label
Label label = new Label( name);
// set position
setTranslateX( x);
setTranslateY( y);
getChildren().addAll( rectangle, label);
}
}
}
这样,您可以使用PathTransition轻松创建节点的动画移动。像这个洗牌机制一样:
import java.util.Random;
import javafx.animation.Animation.Status;
import javafx.animation.PathTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class NodeDemo extends Application {
private double sceneWidth = 1024;
private double sceneHeight = 768;
private int n = 10;
private int m = 10;
double gridWidth = sceneWidth / n;
double gridHeight = sceneHeight / m;
MyNode[][] playfield = new MyNode[n][m];
@Override
public void start(Stage primaryStage) {
Group root = new Group();
// initialize playfield
for( int i=0; i < n; i++) {
for( int j=0; j < m; j++) {
// create node
MyNode node = new MyNode( "Item " + i + "/" + j, i * gridWidth, j * gridHeight, gridWidth, gridHeight);
// add node to group
root.getChildren().add( node);
// add to playfield for further reference using an array
playfield[i][j] = node;
}
}
Scene scene = new Scene( root, sceneWidth, sceneHeight);
primaryStage.setScene( scene);
primaryStage.show();
animate();
}
private void animate() {
Random random = new Random();
int ai = random.nextInt(n);
int aj = random.nextInt(m);
int bi = random.nextInt(n);
int bj = random.nextInt(m);
// make sure that A and B are never the same
if( ai == bi && aj == bj) {
ai++;
if( ai >= n)
ai = 0;
}
MyNode nodeA = playfield[ai][aj];
nodeA.toFront();
MyNode nodeB = playfield[bi][bj];
nodeB.toFront();
// swap on array to keep array consistent
playfield[ai][aj] = nodeB;
playfield[bi][bj] = nodeA;
// A -> B
Path pathA = new Path();
pathA.getElements().add (new MoveTo ( nodeA.getTranslateX() + nodeA.getBoundsInParent().getWidth() / 2.0, nodeA.getTranslateY() + nodeA.getBoundsInParent().getHeight() / 2.0));
pathA.getElements().add (new LineTo( nodeB.getTranslateX() + nodeB.getBoundsInParent().getWidth() / 2.0, nodeB.getTranslateY() + nodeB.getBoundsInParent().getHeight() / 2.0));
PathTransition pathTransitionA = new PathTransition();
pathTransitionA.setDuration(Duration.millis(1000));
pathTransitionA.setNode( nodeA);
pathTransitionA.setPath(pathA);
pathTransitionA.play();
// B -> A
Path pathB = new Path();
pathB.getElements().add (new MoveTo ( nodeB.getTranslateX() + nodeB.getBoundsInParent().getWidth() / 2.0, nodeB.getTranslateY() + nodeB.getBoundsInParent().getHeight() / 2.0));
pathB.getElements().add (new LineTo( nodeA.getTranslateX() + nodeA.getBoundsInParent().getWidth() / 2.0, nodeA.getTranslateY() + nodeA.getBoundsInParent().getHeight() / 2.0));
PathTransition pathTransitionB = new PathTransition();
pathTransitionB.setDuration(Duration.millis(1000));
pathTransitionB.setNode( nodeB);
pathTransitionB.setPath(pathB);
pathTransitionB.play();
pathTransitionA.setOnFinished( new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
if( pathTransitionB.getStatus() == Status.RUNNING)
return;
animate();
}
});
pathTransitionB.setOnFinished( new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
if( pathTransitionA.getStatus() == Status.RUNNING)
return;
animate();
}
});
}
public static void main(String[] args) {
launch(args);
}
public static class MyNode extends StackPane {
public MyNode( String name, double x, double y, double width, double height) {
// create rectangle
Rectangle rectangle = new Rectangle( width, height);
rectangle.setStroke(Color.BLACK);
rectangle.setFill(Color.LIGHTBLUE);
// create label
Label label = new Label( name);
// set position
setTranslateX( x);
setTranslateY( y);
getChildren().addAll( rectangle, label);
}
}
}
这是一个关于如何通过子类化处理单元格的示例。但这只是一种方法:
public class NodeDemo extends Application {
private double sceneWidth = 1024;
private double sceneHeight = 768;
private int n = 10;
private int m = 10;
double gridWidth = sceneWidth / n;
double gridHeight = sceneHeight / m;
MyNode[][] playfield = new MyNode[n][m];
@Override
public void start(Stage primaryStage) {
Group root = new Group();
// initialize playfield
for( int i=0; i < n; i++) {
for( int j=0; j < m; j++) {
MyNode node = null;
// create bug
if( i == 0 && j == 0) {
node = new Bug( "Bug", Color.ORANGE, i, j);
}
// create food
else if( i == 5 && j == 5) {
node = new Food( "Food", Color.GREEN, i, j);
}
// create obstacle
else if( i == 3 && j == 3) {
node = new Obstacle( "Obstacle", Color.GRAY, i, j);
}
// add node to group
if( node != null) {
root.getChildren().add( node);
// add to playfield for further reference using an array
playfield[i][j] = node;
}
}
}
Scene scene = new Scene( root, sceneWidth, sceneHeight);
primaryStage.setScene( scene);
primaryStage.show();
// move bugs
animate();
}
private void animate() {
// TODO
}
public static void main(String[] args) {
launch(args);
}
private class Food extends MyNode {
public Food(String name, Color color, double x, double y) {
super(name, color, x, y);
}
}
private class Obstacle extends MyNode {
public Obstacle(String name, Color color, double x, double y) {
super(name, color, x, y);
}
}
private class Bug extends MyNode {
public Bug(String name, Color color, double x, double y) {
super(name, color, x, y);
}
}
private class MyNode extends StackPane {
public MyNode( String name, Color color, double x, double y) {
// create rectangle
Rectangle rectangle = new Rectangle( gridWidth, gridHeight);
rectangle.setStroke( color);
rectangle.setFill( color.deriveColor(1, 1, 1, 0.7));
// create label
Label label = new Label( name);
// set position
setTranslateX( x * gridWidth);
setTranslateY( y * gridHeight);
getChildren().addAll( rectangle, label);
}
}
}
答案 1 :(得分:0)
您可以从documentation开始查看“使用入门”部分。专注于HelloWorld和LoginForm示例程序等简单示例。
对于你的结构,你可能想要使用GridPane。