2016-05-31 81 views
2

我正在编写一个JavaFX程序,该程序使网格具有随机颜色。当窗口调整大小时,网格应该调整为尽可能大,同时仍然保持平方并在文本底部留出空间。JavaFX GridPane单元格不能自动调整大小内容

一切工作就像它应该,但问题我有的是,当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)); 
    } 
} 

回答

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)); 
+0

感谢这个工作非常出色。你为什么称之为“肮脏的解决方案”? – user2221512

+0

由于@fabian的建议更加干净。我只是为了简单起见而提出这个问题:) – DVarga

1

GridPane使用节点的宽度在布局处理期间。由于除以8的结果可能不是完整的。默认情况下,GridPane位置会将其子项的边界坐标四舍五入为整数值,这会导致您观察到的间隙。

你可以通过设置snapToPixelfalse获得更好的效果:

checkerboardPane.setSnapToPixel(false); 

结果将不会是十全十美。如果您完全想要消除这些差距,请自行将其大小缩小为一个整数值。此外,为了提高效率,只需为该尺寸创建一个NumberBinding。此外Bindings.min可以帮助你获得更简单的代码大小。另外一个Shapefill可以被设置为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); 
    } 
} 
+0

谢谢。你是正确的setSnapToPixel(false)使它更好一点,但仍然不完美。至于舍去,我虽然那也和尝试这样: – user2221512

+0

'rect.widthProperty() \t \t \t \t \t \t .bind(绑定 \t \t \t \t \t \t \t \t。当(scene.widthProperty() .lessThanOrEqualTo(scene.heightProperty()。减去(50))) \t \t \t \t \t \t \t \t。然后(scene.widthProperty()。减(scene.widthProperty()。的intValue()%8).divide (8)) \t \t \t \t \t \t \t \t。否则(scene.heightProperty()中减去(50).subtract(scene.widthProperty()的intValue()%8)。.divide(8)));'但它仍然不起作用。我的逻辑在这里吗?谢谢 – user2221512

+0

我的解决方案不适合你吗?通过使用模运算符,您只需使绑定**更复杂,而不是更少复杂。由于您的最终结果是您比较的值中较小的一个,因此应该应用'min'而不是使用case区分手动执行此操作,并且'IntegerBinding'返回向下舍入为'int'的值。 – fabian

相关问题