JavaFX GridPane плиток одинакового размера, не сохраняющих правильные размеры при добавлении изображений - PullRequest
0 голосов
/ 26 апреля 2020

Я пытаюсь сделать простую игру в шахматы, используя GridPane в JavaFX, и у меня возникают проблемы с работой доски GUI. Когда кусочки добавляются к плиткам в GridPane, другие плитки, на которых нет кусочков, растягиваются или сжимаются. Я хочу, чтобы все плитки GridPane были одинакового размера ВСЕГДА. Плитки в GridPane являются StackPanes. Я хотел бы сохранить их как StackPanes, чтобы в будущем я мог наложить другое изображение или какой-либо текст сверху.

Вот как это выглядит (извините за уродливые цвета):

The sizes of the tiles do not stay the same...

Обратите внимание, что это выглядит так, как я хочу когда все плитки имеют кусочки:

The tile sizes are correct when every tile has a piece.

Ниже приведен код, демонстрирующий мою проблему. Класс WrappedImageView, который я использую, произошел от этого вопроса , а изображение рыцаря (так же как и другие изображения, которые я собираюсь использовать) от здесь .


import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Control;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class SOQuestion extends Application{
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        final int boardSize = 10;
        final GridPane gridPane = new GridPane();
        gridPane.setMinSize(200, 200);
        for (int i = 0; i < boardSize; i++) {
            final ColumnConstraints columnConstraints = new ColumnConstraints(Control.USE_PREF_SIZE, Control.USE_COMPUTED_SIZE, Double.MAX_VALUE);
            columnConstraints.setHgrow(Priority.ALWAYS);
            columnConstraints.setFillWidth(true);
            gridPane.getColumnConstraints().add(columnConstraints);

            final RowConstraints rowConstraints = new RowConstraints(Control.USE_PREF_SIZE, Control.USE_COMPUTED_SIZE, Double.MAX_VALUE);
            rowConstraints.setVgrow(Priority.ALWAYS);
            rowConstraints.setFillHeight(true);
            gridPane.getRowConstraints().add(rowConstraints);
        }

        Color color1 = new Color(1.0,0,0,1);
        Color color2 = new Color(0,1.0,0, 1);

        for (int i = 0; i < boardSize; i++) {
            for (int j = 0; j < boardSize; j++) {
                StackPane child = new StackPane();

                SOQuestion.WrappedImageView img = new SOQuestion.WrappedImageView(new Image(getClass().getResourceAsStream(
                        "/resources/knight_black.png")));

                child.setBackground(new Background(
                    new BackgroundFill((i+j) % 2 == 0 ? color1 : color2, CornerRadii.EMPTY, Insets.EMPTY)));

                if(Math.random() < 0.1) //to randomly place pieces around the board for demonstration
                    child.getChildren().addAll(img);

                child.setMinSize(0,0);

                GridPane.setRowIndex(child, i);
                GridPane.setColumnIndex(child, j);
                gridPane.getChildren().add(child);
            }
        }

        Scene scene = new Scene(gridPane, 800, 600);

        primaryStage.setScene(scene);
        primaryStage.show();
    }
    class WrappedImageView extends ImageView
    {
        WrappedImageView(Image im)
        {
            super(im);
            setPreserveRatio(false);
        }

        @Override
        public double minWidth(double height)
        {
            return 40;
        }

        @Override
        public double prefWidth(double height)
        {
            Image I=getImage();
            if (I==null) return minWidth(height);
            return I.getWidth();
        }

        @Override
        public double maxWidth(double height)
        {
            return 16384;
        }

        @Override
        public double minHeight(double width)
        {
            return 40;
        }

        @Override
        public double prefHeight(double width)
        {
            Image I=getImage();
            if (I==null) return minHeight(width);
            return I.getHeight();
        }

        @Override
        public double maxHeight(double width)
        {
            return 16384;
        }

        @Override
        public boolean isResizable()
        {
            return true;
        }

        @Override
        public void resize(double width, double height)
        {
            setFitWidth(width);
            setFitHeight(height);
        }
    }
}

Я думал об использовании пустого изображения-заполнителя, которое помещается в каждую "пустую" плитку, но я уверен, что есть лучший способ.

Я смотрел на следующие другие сообщения SO, пытаясь чтобы заставить это работать, но безрезультатно:

Заранее спасибо за помощь; извините за такой длинный пост!

РЕДАКТИРОВАТЬ: Я также хотел бы убедиться, что размер плитки и панели сетки изменяются соответствующим образом при изменении размера окна, чтобы оно заполняло все окно, так как оно делает с текущим кодом.

1 Ответ

0 голосов
/ 26 апреля 2020

Использование setPercentWidth(100.0/boardSize) и setPercentHeight(100.0/boardSize), как предположил James_D, сработало как шарм. Я решил придерживаться GridPane вместо TilePane, потому что он лучше подходил для других вещей, которые я планирую сделать в программе. Спасибо!

...