JavaFX GridPane单元格不会自动调整大小到内容

时间:2016-05-31 23:56:12

标签: java user-interface javafx gridpane

我正在编写一个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));
    }
}

2 个答案:

答案 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);
    }
}