添加图像时,相同大小的图块的 JavaFX GridPane 未保持正确的大小
JavaFX GridPane of Equally-sized tiles not keeping correct sizes when images are added
我正在尝试使用 JavaFX 中的 GridPane 制作一个简单的国际象棋游戏,但我无法让棋盘 GUI 正常工作。当块被添加到 GridPane 中的图块时,其他没有任何块的图块会被拉伸或收缩。我希望所有 GridPane 的图块始终具有相同的大小。 GridPane 中的磁贴是 StackPanes。我想将它们保留为 StackPanes,以便将来可以在顶部覆盖另一个图像或一些文本。
这是它的样子(对不起,丑陋的颜色):
请注意,当所有瓷砖上都有碎片时,它看起来就像我想要的那样:
下面是一些演示我的问题的代码。我使用的 WrappedImageView
class 来自 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);
}
}
}
我考虑过在每个 "empty" 拼贴中使用空白占位符图像,但我确信有更好的方法。
我查看了以下其他 SO post 试图让它工作,但无济于事:
JavaFX - force the child of a GridPane to fit the size of the cell
JavaFX ImageView resize in StackPane
在此先感谢您的帮助;抱歉这么长post!
编辑: 我还想确保在 window 调整大小时适当地调整图块和网格窗格的大小,以便它填充整个 window, 与当前代码一样。
按照 James_D 的建议使用 setPercentWidth(100.0/boardSize)
和 setPercentHeight(100.0/boardSize)
非常有效。我决定坚持使用 GridPane
而不是 TilePane
因为它更适合我计划在程序中做的其他事情。谢谢!
我正在尝试使用 JavaFX 中的 GridPane 制作一个简单的国际象棋游戏,但我无法让棋盘 GUI 正常工作。当块被添加到 GridPane 中的图块时,其他没有任何块的图块会被拉伸或收缩。我希望所有 GridPane 的图块始终具有相同的大小。 GridPane 中的磁贴是 StackPanes。我想将它们保留为 StackPanes,以便将来可以在顶部覆盖另一个图像或一些文本。
这是它的样子(对不起,丑陋的颜色):
请注意,当所有瓷砖上都有碎片时,它看起来就像我想要的那样:
下面是一些演示我的问题的代码。我使用的 WrappedImageView
class 来自 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);
}
}
}
我考虑过在每个 "empty" 拼贴中使用空白占位符图像,但我确信有更好的方法。
我查看了以下其他 SO post 试图让它工作,但无济于事:
JavaFX - force the child of a GridPane to fit the size of the cell
JavaFX ImageView resize in StackPane
在此先感谢您的帮助;抱歉这么长post!
编辑: 我还想确保在 window 调整大小时适当地调整图块和网格窗格的大小,以便它填充整个 window, 与当前代码一样。
按照 James_D 的建议使用 setPercentWidth(100.0/boardSize)
和 setPercentHeight(100.0/boardSize)
非常有效。我决定坚持使用 GridPane
而不是 TilePane
因为它更适合我计划在程序中做的其他事情。谢谢!