所以,我试图在javaFX中显示棋盘。我将不得不执行不同的操作并绘制一些图块,因此我选择为每个图块使用Canvas,并使用GridPane以网格方式为我安排它们。
不幸的是,我在调整网格图块的大小时遇到了一些问题;我希望我的整个棋盘自动调整它的大小到场景。因此,我在GridPane的高度和宽度属性中添加了一个ChangeListener,它负责调整tile的大小。这仅在窗口变大时才有效,当窗口缩小到较小尺寸时,一切仍然变大!
这是我提出的最短SSCCE,它可以重现我的问题:
package chessboardtest;
import javafx.application.Application;
import javafx.beans.value.*;
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.canvas.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.stage.Stage;
public class ChessboardTest extends Application {
final int size = 10;
@Override
public void start(Stage primaryStage) {
VBox root = new VBox();
final GridPane chessboard = new GridPane();
fillChessboard(chessboard, size);
ChangeListener<Number> resizeListener = new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) {
double newWidth = chessboard.getWidth() / size;
double newHeight = chessboard.getHeight() / size;
for(Node n: chessboard.getChildren()) {
Canvas canvas = (Canvas)n;
canvas.setWidth(newWidth);
canvas.setHeight(newHeight);
}
}
};
chessboard.widthProperty().addListener(resizeListener);
chessboard.heightProperty().addListener(resizeListener);
root.getChildren().add(chessboard);
root.setPadding(new Insets(10));
VBox.setVgrow(chessboard, Priority.ALWAYS);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("chessboard");
primaryStage.setScene(scene);
primaryStage.show();
}
void fillChessboard(GridPane pane, int size) {
class RedrawListener implements ChangeListener<Number> {
Color color;
Canvas canvas;
public RedrawListener(Canvas c, int i) {
if(i % 2 == 0) {
color = Color.BLACK;
}
else {
color = Color.WHITE;
}
canvas = c;
}
@Override
public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) {
canvas.getGraphicsContext2D().setFill(color);
canvas.getGraphicsContext2D().fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
}
}
for(int row = 0; row < size; row++) {
for(int col = 0, i = row; col < size; col++, i++) {
Canvas c = new Canvas();
RedrawListener rl = new RedrawListener(c, i);
c.widthProperty().addListener(rl);
c.heightProperty().addListener(rl);
pane.add(c, row, col);
}
}
}
public static void main(String[] args) {
launch(args);
}
}
答案 0 :(得分:5)
如果你不需要画布(而且你可能不喜欢),只需使用StackPane
s作为方块,并使它们填充宽度和高度。您始终可以向StackPane
添加画布(或其他任何内容)以显示其内容。
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.control.Control;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Chessboard extends Application {
@Override
public void start(Stage primaryStage) {
GridPane root = new GridPane();
final int size = 8 ;
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col ++) {
StackPane square = new StackPane();
String color ;
if ((row + col) % 2 == 0) {
color = "white";
} else {
color = "black";
}
square.setStyle("-fx-background-color: "+color+";");
root.add(square, col, row);
}
}
for (int i = 0; i < size; i++) {
root.getColumnConstraints().add(new ColumnConstraints(5, Control.USE_COMPUTED_SIZE, Double.POSITIVE_INFINITY, Priority.ALWAYS, HPos.CENTER, true));
root.getRowConstraints().add(new RowConstraints(5, Control.USE_COMPUTED_SIZE, Double.POSITIVE_INFINITY, Priority.ALWAYS, VPos.CENTER, true));
}
primaryStage.setScene(new Scene(root, 400, 400));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
答案 1 :(得分:2)
这是一个很好的解决方案,但在Java FX中使用数据绑定可以更轻松地调整大小。您可以通过这种方式隐藏所有侦听器业务。 这是一个很像詹姆斯D的解决方案,但使用矩形插入Canvases的正方形:
public class ResizeChessboard extends Application {
GridPane root = new GridPane();
final int size = 8;
public void start(Stage primaryStage) {
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
Rectangle square = new Rectangle();
Color color;
if ((row + col) % 2 == 0) color = Color.WHITE;
else color = Color.BLACK;
square.setFill(color);
root.add(square, col, row);
square.widthProperty().bind(root.widthProperty().divide(size));
square.heightProperty().bind(root.heightProperty().divide(size));
}
}
primaryStage.setScene(new Scene(root, 400, 400));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}