java - 在JavaFX中将二维数组显示为网格

标签 java arrays javafx grid

对于我的 Java 类(class)作业,我必须创建一个基于网格的动画。基本上我目前有一个包含某些值的二维数组,这些值每次运行程序时都会发生变化。例如,它可以是 20x20 二维数组,或 32x32 等。数组内部存储某些值,字符代表动物,数字代表食物。动物闻到食物的气味,然后在程序的每个循环后向食物移动,因此它们在阵列中的位置在每个循环后都会发生变化。该程序的工作原理与我提出的问题并不真正相关。

基本上,我现在必须在 JavaFX 中实现这一点(它当前在控制台中工作,每个周期将数组显示为网格)。我只是想知道在 JavaFX 中最适合使用哪个控件来显示二维数组,或者是否有人可以为我指出如何开始编码的正确方向?

我是 java(和 JavaFX)新手,所以不确定要使用哪些控件...

最佳答案

我不会使用控件。我宁愿为数组中的每个项目创建一个节点并将它们放在场景中。像这样的事情:

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

        }

    }

}

关于java - 在JavaFX中将二维数组显示为网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27870674/

相关文章:

multithreading - JavaFX TableView 更新频繁

java - 为什么 matlabcontrol 在代理创建时中断调用线程?

java - 在restful post调用中部分反序列化json对象

java - foreach 语法中的三元运算符

javascript - 加载时文本内容随机化

arrays - Redux、React、MapStateToProps : Retrieve a specific element in an array from the redux state tree

arrays - 如何通过与swift中的另一个元素数组进行比较来从元素数组生成随机字符串?

java - 通用类型与给定的方法签名不兼容?

java - 为什么在 Start() 方法上声明按钮会使场景变得无色?

java - 如何将一个基本异常替换为另一个异常?