当前位置: 首页 > 知识库问答 >
问题:

JavaFX GridPane单元格不能根据内容自动调整大小

曾晨
2023-03-14

我正在编写一个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个答案

阎伟志
2023-03-14

GridPane在布局过程中使用节点的宽度。因为除以8的结果可能不是整数。默认情况下,GridPane将其子级的边界协叉舍入为整数值,这导致您观察到的间隙。

通过将< code > snaptopexel 设置为< code>false,可以获得更好的结果:

checkerboardPane.setSnapToPixel(false);

然而,结果并不完美。如果您完全想消除间隙,请自己将大小四舍五入到整数。此外,为了提高效率,只需为大小创建一个NumberBinding。此外,绑定。min可以帮助您获得更简单的尺寸代码。此外,可以直接将形状填充设置为颜色

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

赫连法
2023-03-14

当你将值绑定到<code>场景的高度时,这些小间隙来自所有<code>矩形的宽度计算。

肮脏的解决方案是使用GridPane.setMargin(Node子节点,插图值)在矩形周围添加一个-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));
 类似资料:
  • 我想调整SVG元素的尺寸以适应其内容。 JSfiddle:http://jsfiddle.net/4pD9N/ 这里我有一个例子。SVG应该“收缩”以适应每边10像素的元素边距。换句话说:我想为未使用的空间裁剪svg... 我知道我必须使用getBBox。但是我如何计算总宽度和总高度呢?

  • 问题内容: 我正在开发类似iGoogle的应用程序。使用iframe显示其他应用程序(在其他域上)的内容。 如何调整iframe的大小以适合iframe内容的高度? 我试图破译Google使用的javascript,但它被混淆了,到目前为止,在网络上搜索毫无结果。 更新: 请注意,内容是从其他域加载的,因此适用同源策略。 问题答案: 我们遇到了这类问题,但与您的情况略有不同我们向其他域上的网站提供

  • 问题内容: 在以Swift编写的iOS应用程序中使用自动布局时,如何根据内容调整textField的大小? 加载视图时以及用户键入时,文本字段将根据需要调整大小以适合其内容。 理想情况下,文本字段将在某个点(例如6行)处停止调整大小,并变为可滚动。 问题答案: 您必须使用而不是。 然后,您可以使用该方法。 但是首先,您必须知道一条线的高度。您可以使用以下方法获取该信息: 之后,只需在方法内部调用方

  • 问题内容: 我在一个网格中嵌套了两个网格。不幸的是,右边的嵌套网格设置行的高度,以使左边和右边的网格都具有相同的高度,额外的空间在class的div之间共享。如何设置右侧嵌套网格的行以调整内容的大小,使其与左侧嵌套行的高度相同? 问题答案: 您可以尝试 参考 您也可以只使用或

  • 问题内容: 我正在将AutoSizing单元格与Autolayout和UICollectionView一起使用。 我可以在单元初始化的代码中指定约束: 但是,由于该单元尚未添加到中,该应用程序崩溃了。 问题 在该阶段的生命周期,可以添加一个约束的? 有没有作出任何默认方式的equal to the of thewithout accessing an instance of or? 编辑 这个问题

  • 问题内容: 我试图创建一个Excel工作簿,在保存工作簿之前可以自动设置或自动调整列的宽度。 我一直在阅读的Python的Excel的教程在xlwt是模仿xlrd者(如发现某些功能的希望,,,,等…)。例如,假设我有以下几点: 与xlrd中提供的功能类似,除了前者允许您修改内容(如果用户已设置) 假设xlwt确实提供了我想要的功能,我计划再次遍历每个工作表,但是这次要跟踪占用特定列最多空间的内容,