GridPane与ScrollPane内部的间隙呈现错误

时间:2018-05-23 03:30:01

标签: java javafx scrollpane gridpane

我想要一个带方形单元格的矩形网格,可以缩放和拖动(就像你的地图一样)。所以我把它放在ScrollPane中,尽管它在某些尺寸上表现得相当奇怪。网格的大小将动态变化。

在图片上有一个大小为20x20的网格。 Grid of size 20x20

  1. 网格内并未显示所有间隙。请注意,它应为20格 但事实并非如此。 Vgap和Hgap都是1。
  2. 网格本身比内容大,这不好,因为当它被缩放时,我可以拖动到网格的边框之外。
  3. 当它小于滚动窗格时,我想将GridPane置于ScrollPane 中心。 (Gridpane alignment="CENTER"显然没有做任何事情)
  4. 最小,完整且可验证的示例

    FXML:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.ScrollPane?>
    <?import javafx.scene.layout.GridPane?>
    
    <ScrollPane hbarPolicy="NEVER" hvalue="0.5" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" pannable="true" prefHeight="400.0" prefWidth="600.0" vbarPolicy="NEVER" vvalue="0.5" xmlns="http://javafx.com/javafx/9" xmlns:fx="http://javafx.com/fxml/1" fx:controller="bug.app.Bug">
        <GridPane fx:id="gridPane" alignment="CENTER" hgap="1.0" style="-fx-background-color: red;" vgap="1.0">
        </GridPane>
    </ScrollPane>
    

    Controller + Main:

    package bug.app;
    
    import javafx.application.Application;
    import javafx.beans.binding.DoubleBinding;
    import javafx.beans.property.DoubleProperty;
    import javafx.beans.property.SimpleDoubleProperty;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.geometry.Insets;
    import javafx.scene.Node;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.scene.layout.*;
    import javafx.scene.paint.Color;
    import javafx.stage.Stage;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Bug extends Application {
        private static final int HEIGHT = 20;
        private static final int WIDTH = 20;
        private static final double MIN_CELL_SIZE = 2;
        @FXML private GridPane gridPane;
        private DoubleProperty zoomRatio = new SimpleDoubleProperty(5);
    
        @FXML
        private void initialize() {
            final DoubleBinding cellSizeBinding = zoomRatio.multiply(MIN_CELL_SIZE);
    
            List<Node> cells = new ArrayList<>(HEIGHT * WIDTH);
            for (int row = 0; row < HEIGHT; row++) {
                for (int col = 0; col < WIDTH; col++) {
                    final Pane cell = new Pane();
                    cell.setBackground(new Background(new BackgroundFill(Color.YELLOW, CornerRadii.EMPTY, Insets.EMPTY)));
    
                    cell.setMinSize(MIN_CELL_SIZE, MIN_CELL_SIZE);
                    cell.setMaxWidth(Region.USE_PREF_SIZE);
                    cell.setMaxHeight(Region.USE_PREF_SIZE);
                    cell.prefWidthProperty().bind(cellSizeBinding);
                    cell.prefHeightProperty().bind(cellSizeBinding);
    
                    GridPane.setConstraints(cell, col, row, 1, 1);
    
                    cells.add(cell);
                }
            }
            gridPane.getChildren().clear();
            gridPane.getChildren().addAll(cells);
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
        @Override
        public void start(Stage primaryStage) throws IOException {
            Parent root = FXMLLoader.load(
                    getClass().getResource("/view/bugView.fxml"));
            final Scene scene = new Scene(root, 600, 400);
    
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    }
    

    NB:我选择Pane作为Cell,因为我想将它子类化并最终填充它(可能是Shapes?),使用不同的颜色将正方形划分为1-4个部分。想象一下,两个或四个三角形形成一个正方形。我也想优雅地调整大小(AFAIK Shapes不可调整大小),也许以某种方式将内部形状的大小绑定到Panes的大小将会起到魔力。我还没有那么远,但也可以随意提出建议。

2 个答案:

答案 0 :(得分:0)

将网格窗格包裹在堆栈窗格内,这将使网格窗格中心

答案 1 :(得分:0)

问题1&amp; 2

我找到问题 1。 2。的解决方法,省略了Vgap和Hgap,因为它显然是错误的。

我没有使用GridPane的gap属性,而是在每个单元格上设置边距:

GridPane.setMargin(cell, new Insets(0.5));

然而,由于GridPane上的默认snapToPixel="true",因此将边距舍入为1,从而导致2px的间隙。这是不方便的,因为我希望方块小到2x2px,所以2px的间隙太大了。我可能会在GridPane上将snapToPixel设置为false。需要更多测试。

问题3

我尝试按照@Silas Gyeme的建议将GridPane包装在StackPane中。

简单地将它包装在StackPane中是不够的。我必须同时设置fitToHeight="true"&amp; ScrollPane上的fitToWidth="true"

还必须将单元格的minSize绑定到cellSizeBinding,因为当我缩小窗口时,它正在调整方块的大小。

cell.minWidthProperty().bind(cellSizeBinding);
cell.minHeightProperty().bind(cellSizeBinding);

编辑:我尝试省略StackPane,但实际上并不需要它!只设置fitToHeightfitToWidth就足够了,GridPane可以很好地延伸。