在JavaFX中将2d数组显示为网格

时间:2015-01-09 23:01:25

标签: java arrays javafx grid

对于我的Java课程,我必须创建一个基于网格的动画。基本上我目前有一个包含某些值的二维数组,每次运行程序时都会更改。例如,它可以是20x20 2d阵列,或32x32等。在阵列内部存储某些值,字符代表动物,数字代表食物。动物闻到食物然后在程序的每个循环后移向食物,因此它们在阵列中的位置在每个循环后改变。该计划的运作方式与我提出的问题无关。

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

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

2 个答案:

答案 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