JavaFX — использование циклов в GridPane?

Я пытаюсь использовать два цикла for для автоматического добавления узлов ImageView в каждое место. При использовании цикла for я получаю сообщение об ошибке. Когда я комментирую код цикла for с помощью только одного оператора для добавления узла ImageView, код, похоже, работает. Можете ли вы использовать циклы for для заполнения GridPane? Если да, то что я делаю неправильно? Если нет, что можно использовать в качестве решения?

Мои занятия:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class GridCreation extends Application {
@Override
public void start(Stage gameStage) throws Exception {
    GridPane grid = new GridPane();
    Image backOfCardsImg = new Image("images/naruto_shipuden_logo.png");
    ImageView backOfCards = new ImageView(backOfCardsImg);
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                grid.add(backOfCards, i, j);

            }
        }

    //grid.add(backOfCards, 1,1);
    Scene scene = new Scene(grid);
    gameStage.setTitle("MemoryGame");
    gameStage.setScene(scene);
    gameStage.show();
}

public static void main(String[] args) {
    launch(args);
}
}

Изменить: для кода:

grid.add(backOfCards, i, j);

Я изменил строку кода на

grid.add(new ImageView(backOfCardImg), i, j);

это, казалось, решило проблему, но может ли кто-нибудь объяснить мне, почему первый вариант не работает?


person leftlopez    schedule 07.12.2014    source источник
comment
ImageView — это Node, и вы не можете использовать его повторно, иначе вы получите следующее исключение: Children: duplicate children added. Второе решение работает, потому что вы создаете одно новое изображение для каждой ячейки сетки.   -  person José Pereda    schedule 07.12.2014
comment
Я хочу повторно использовать изображение и добавить его в каждую сетку. Есть ли какое-либо решение для этого?   -  person leftlopez    schedule 07.12.2014
comment
Поскольку узел FX может иметь только одного родителя и может быть добавлен только один раз к этому родителю, вам необходимо создавать новый ImageView() каждый раз, когда вы хотите показать это изображение в своей сетке. Он не будет дублировать само изображение, а только контейнер/элемент управления JavaFX для представления.   -  person Jens-Peter Haack    schedule 07.12.2014


Ответы (1)


Это может быть полезным началом для игры памяти в fx. Он использует собственное расширение ImageView для анимации поворота и фокусировки, а также для работы с общим изображением задней стороны. Только графика, никакой игровой логики.

public class MemoryGame extends Application {
    final int rows = 4;
    final int columns = 4;
    CardView views[][] = new CardView[rows][];

    public static class CardView extends ImageView {
        static final double scale = 0.95;
        static DropShadow shadowhoover = new DropShadow(5, 4, 4, Color.rgb(50, 60, 50));
        static DropShadow shadowdown = new DropShadow(2, 2, 2, Color.rgb(50, 60, 50));
        static Image backside = null;
        public static void setbackside(Image image) { backside = image; }

        public CardView(Image image) { 
            super(backside); 
            setRotationAxis(new Point3D(0, 200,0));
            setScaleX(scale);
            setScaleY(scale);
            setEffect(shadowdown);
            setOnMouseEntered(m -> {
                setEffect(shadowhoover);
                setScaleX(scale*1.01);
                setScaleY(scale*1.01);
            });
            setOnMouseExited(m -> {
                setEffect(shadowdown);
                setScaleX(scale);
                setScaleY(scale);
            });
            setOnMouseClicked(m -> {      
                RotateTransition r1 = new RotateTransition(Duration.millis(300), this);
                r1.setByAngle(90);
                r1.setOnFinished(e -> setImage(image));
                RotateTransition r2 = new RotateTransition(Duration.millis(300), this);
                r2.setByAngle(-90);

                RotateTransition r3 = new RotateTransition(Duration.millis(300), this);
                r3.setByAngle(90);
                r3.setOnFinished(e -> setImage(backside));
                RotateTransition r4 = new RotateTransition(Duration.millis(300), this);
                r4.setByAngle(-90);

                new SequentialTransition(r1, r2, new PauseTransition(Duration.millis(1000)), r3, r4).play();
            });
        }
    }

    @Override
    public void start(Stage gameStage) throws Exception {
        GridPane grid = new GridPane();
        grid.setBackground(new Background(new BackgroundFill(Color.rgb(140, 200, 140), new CornerRadii(0), new Insets(0))));
        grid.setHgap(5);
        grid.setVgap(5);
        Image back = new Image(MemoryGame.class.getResource("card-back.png").toExternalForm(), 140, 200, true, true);
        Image front = new Image(MemoryGame.class.getResource("card-1.png").toExternalForm(), 140, 200, true, true);
        CardView.setbackside(back);
        for (int r = 0; r < rows; r++) {
            views[r] = new CardView[columns];
            for (int c = 0; c < columns; c++) {
                CardView view = new CardView(front); // different front images of course...
                views[r][c] = view;

                HBox box = new HBox(5);
                box.getChildren().add(views[r][c]);
                grid.add(box, c, r);

            }
        }

        //grid.add(backOfCards, 1,1);
        Scene scene = new Scene(grid);
        gameStage.setTitle("MemoryGame");
        gameStage.setScene(scene);
        gameStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
person Jens-Peter Haack    schedule 07.12.2014