我正在编写一个JavaFX程序,它创建一个随机颜色的网格。调整窗口大小时,网格应调整,使其尽可能大,同时仍保持正方形,并在文本的底部留出空间。
一切都像它应该的那样工作,但问题我所拥有的是GridPane在调整大小时留下的空白很小。窗口调整大小时,间隙的大小会略有变化。有人可以帮我弄清楚如何消除这些差距吗?我包括完整的代码。这不是太长。谢谢。
import java.util.Random;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
/**
* Uses a 2D array to populate a grid of squares with random colors.
*/
public class Lab7 extends Application {
private Color[][] colorGrid = new Color[8][8];
private int redCellCount = 0;
/**
* Tells the program to start with the start() method since it is a JavaFX
* Application
*
* @param args
* arguments supplied to the program
*/
public static void main(String[] args) {
Application.launch(args);
}
/**
* Constructor for the class instantiates the 2D array of Color objects with
* random colors.
*/
public Lab7() {
// array of 12 awt colors not including white since it is used as the
// background color
Color[] colorList = { Color.BLACK, Color.BLUE, Color.CYAN, Color.DARKGREY, Color.GRAY, Color.GREEN,
Color.LIGHTGRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED, Color.YELLOW };
// populate the 2D array of colors with random colors from the colorList
for (int i = 0; i < colorGrid.length; i++) {
for (int j = 0; j < colorGrid[i].length; j++) {
Random rand = new Random();
int colorCode = rand.nextInt(12);
if (colorCode == 10) {
redCellCount++;
}
colorGrid[i][j] = colorList[colorCode];
}
}
}
/*
* overridden method of the Application class. This is the entry point of
* the JavaFX application
*/
@Override
public void start(Stage stage) throws Exception {
// a GridPane that will hold the checkerboard of colors
GridPane checkerboardPane = new GridPane();
// a root pane for the layout
BorderPane parentPane = new BorderPane();
// create the scene and set the root node as the BorderPane and have the
// initial size be 400x400 pixels and set the background color to white
Scene scene = new Scene(parentPane, 400, 400);
parentPane.setStyle("-fx-background-color: " + toRGBCode(Color.WHITE));
// a Text object to display the number of red squares
Text redCellCountText = new Text("There are " + redCellCount + " red squares.");
// put the colorGrid in the center of the GridPane and the
// redCellCountText to the bottom
parentPane.setCenter(checkerboardPane);
parentPane.setBottom(redCellCountText);
// create 64 rectangles, fill them with the colors in the colorGrid and
// set a mouse click event handler
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
Rectangle rect = new Rectangle(scene.getWidth() / 8, scene.getWidth() / 8);
// bind the width property of the rectangle to 1/8 of the
// smaller of the scene width or height, leave 50 pixels at the
// bottom for the Text
rect.widthProperty()
.bind(Bindings
.when(scene.widthProperty().lessThanOrEqualTo(scene.heightProperty().subtract(50)))
.then(scene.widthProperty().divide(8))
.otherwise(scene.heightProperty().subtract(50).divide(8)));
// bind the width of the rectangle to its height so it will
// always be square
rect.heightProperty().bind(rect.widthProperty());
// set the color of the rectangle to correspond to the colorGrid
rect.setStyle("-fx-fill: " + toRGBCode(colorGrid[i][j]));
// set an event listener for the rectangle to handle when the
// user clicks on it
rect.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// if the rectangle is not red
if (!((Rectangle) event.getSource()).getFill().equals(Color.RED)) {
// set its color to red
((Rectangle) event.getSource()).setFill(Color.RED);
// increment the redCellCount and update the text
redCellCount++;
redCellCountText.setText("There are " + redCellCount + " red squares.");
}
}
});
// add the rectangle to its respective square in the GridPane
checkerboardPane.add(rect, j, i);
}
}
// set the scene in the stage and set its title
stage.setScene(scene);
stage.setTitle("Lab7");
// show the stage to make it visible
stage.show();
}
/**
*
* @param color
* The JavaFX Color to convert
* @return the rgb code representing the JavaFX Color
*/
public static String toRGBCode(Color color) {
return String.format("#%02X%02X%02X", (int) (color.getRed() * 255), (int) (color.getGreen() * 255),
(int) (color.getBlue() * 255));
}
}
答案 0 :(得分:1)
当你将值绑定到Rectangles
的高度时,这些小差距来自于计算所有Scene
的宽度。
肮脏的解决方案是使用GridPane.setMargin(Node child, Insets value):
在矩形周围添加-1边距// add the rectangle to its respective square in the GridPane
checkerboardPane.add(rect, j, i);
GridPane.setMargin(rect, new Insets(-1, -1, -1, -1));
答案 1 :(得分:1)
GridPane
在布局过程中使用节点的宽度。由于除以8的结果可能不是完整的。默认情况下,GridPane
个地方会将其子女的边界坐标变为整数值,这会导致您观察到的差距。
将snapToPixel
设置为false
:
checkerboardPane.setSnapToPixel(false);
但结果并不完美。如果您完全想要消除间隙,请将尺寸缩小到自己的整数值。此外,为了效率,只需为大小创建一个NumberBinding
。此外,Bindings.min
可以帮助您获得更简单的代码。另外,Shape
的{{3}}可以直接设置为Color
:
NumberBinding size = Bindings.min(scene.widthProperty(),
scene.heightProperty().subtract(50))
.divide(8);
// binding for size rounded down
NumberBinding roundedSize = Bindings.createIntegerBinding(() -> size.intValue(), size);
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
Rectangle rect = new Rectangle();
rect.widthProperty().bind(roundedSize);
rect.heightProperty().bind(roundedSize);
rect.setFill(colorGrid[i][j]);
// click handler
checkerboardPane.add(rect, j, i);
}
}