I'm trying to make a simple chess game using a GridPane in JavaFX and I'm having trouble getting the board GUI to work. When pieces are added to tiles in the GridPane, the other tiles that don't have any piece on them get stretched out or shrunk. I want all of the tiles GridPane to be the same size ALWAYS. The tiles in the GridPane are StackPanes. I would like to keep them as StackPanes so that I can overlay another image or some text on top in the future.
Here is what it looks like (sorry about the ugly colors):
Note that it looks just like I want it to when all the tiles have pieces on them:
Below is some code that demonstrates my problem. The WrappedImageView
class I am using came from this question, and the image of the knight (as well as the other images I intend to use) is from here.
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);
}
}
}
I have thought about using a blank placeholder image that goes in every "empty" tile, but I'm sure there's a better way.
I have looked at the following other SO posts trying to get this to work, but to no avail:
Thanks in advance for the help; sorry for such a long post!
EDIT: I would also like to make sure the tiles and grid pane resize appropriately when the window is resized so that it fills the entire window, as it does with the current code.
Using setPercentWidth(100.0/boardSize)
and setPercentHeight(100.0/boardSize)
as James_D suggested worked like a charm. I decided to stick with a GridPane
instead of a TilePane
because it was better suited for other things I plan to do in the program. Thanks!