Rich Starbuck
Rich Starbuck

Reputation: 55

JPanel: extra spaces between borders of nested GridLayout tables

I'm working on my first Java Swing project (really my first GUI project, unless you count client-side web programming), and I'm having an aesthetic issue. I'm making a Sudoku board in a JPanel. The panel is laid out with a 3x3 GridLayout, with each of its nine cells containing JPanel filled with another 3x3 GridLayout. The outer grid has wider borders to indicate the "boxes" of a Sudoku board, and the inner grid thinner borders to display the "cells" (here's a screenshot if you need help visualizing it).

The problem is that I'm getting extra space between the borders of the inner and outer grids, which looks just terrible. I've tried setting the insets to zero explicitly, which didn't do anything. The only way I can think to fix it is to eliminate the GridLayout nesting altogether and instead use one 9x9 grid, setting the individual cell borders to be thicker at the top/bottom/left/right where appropriate; however, each cell's border changes color and thickness when it gains focus, and I can't think of a graceful way to implement that strategy. I've also been looking into other layouts, but GridLayout seems perfect for this purpose (each cell should be the same size).

Here's the constructor for BoardPanel (extends JPanel), I tried to omit any extraneous code:

BoardPanel(Board newBoardData)
{
    /**
     * Instance variable initializations, call to super(), etc. omitted.
     */     

    // Outer grid initialization
    // In pictures, .getBoxWidth() and .getBoxHeight both return (int)3
    setLayout(new GridLayout(boardData.getBoxWidth(), boardData.getBoxHeight(), 0, 0));
    setBorder(new LineBorder(colorGridBorders, 2));

    // Inner grid array; .getBoardSize() returns (int)9
    JPanel innerBoxGridPanels[] = new JPanel[boardData.getBoardSize()];
    GridLayout innerBoxGridLayout = new GridLayout(boardData.getBoxHeight(), boardData.getBoxWidth(), 0, 0);
    LineBorder innerBoxLineBorder = new LineBorder(colorGridBorders, 1);

    for (int columnIndex = 0; columnIndex < boardData.getBoardSize(); ++columnIndex)
    {
        for (int rowIndex = 0; rowIndex < boardData.getBoardSize(); ++rowIndex)
        {
            // CellPanel derives from JPanel; has a call to setBorder() to create inner grid lines
            cellPanes[columnIndex][rowIndex] = new CellPanel(columnIndex, rowIndex, boardData.getCell(columnIndex, rowIndex));
        }
    }

    for (int box = 0; box < boardData.getBoardSize(); ++box)
    {
        // Inner grid initialization
        innerBoxGridPanels[box] = new JPanel(innerBoxGridLayout);
        innerBoxGridPanels[box].setBorder(innerBoxLineBorder);

        // Adding cells to inner grid
        for (int cell = 0; cell < boardData.getBoardSize(); ++cell)
        {

            innerBoxGridPanels[box].add(cellPanes
                                [( cell % boardData.getBoxWidth() )
                                  + ( ( box % boardData.getBoxHeight() ) * boardData.getBoxWidth() )]
                                [( cell / boardData.getBoxWidth() )
                                  + ( (box / boardData.getBoxHeight() ) * boardData.getBoxHeight() ) ]);
        }

        // Adding inner grids to outer grid
        add(innerBoxGridPanels[box]);
    }
}

Here's a screenshot of the rendered board at various sizes. In the upper-right image, you can see that if you adjust the window size just right you can get rid of most of the extra space (there's still some at the edges though).

Has anyone had this sort of problem with nested GridLayouts before and found a solution? Any help would be greatly appreciated, I've been pulling my hair out over this for over a day now.

Upvotes: 2

Views: 1201

Answers (1)

Evans
Evans

Reputation: 1599

Seems like a problem with the window size. Let´s say there are 2 panels horizontally inside an outer panel. The outer pane has a border of size 2 and the inner panels have a border of size 1.

If the window has a size of 18 for example, we have

  • 2px for outer border
  • 1px for inner border
  • 5px for panel content
  • 1px for inner border
  • 1px for inner border
  • 5px for panel content
  • 1px for inner border
  • 2px for outer border

So there is no space and both inner panels have same size

If for whatever reason the window size is changed to 19, there is a need to create a gap between the panels to mantain them of equal size.

If the size is 20, both panels get +1 to his size and there is no gap needed.

To solve this you can use a fixed size of the window (one you know has no gaps), or add a padding to the outer panel when the window is resized so the padding makes the rest of the frame to have a size that produces no gaps. (in your case, if my maths are fine, should be 20 + x/3)

If you want to discard the use of nested panels and change the cell border when has the focus, you need a LineBorder instance for each cell. In your code, all cells are using the same LineBorder instance.

Upvotes: 3

Related Questions