0

I am trying to properly size a JPanel so that it exactly fits a rendered 8 x 8 checkerboard. When I zoom in using a paint program, I notice two extra pixels added to both the width and height ...

screenshot

This isn't too bad but when I surround this CENTER panel with other JPanels (NORTH, SOUTH, EAST, WEST in the JFrame using BorderLayout) the white gap is noticeable.

I get around the issue by subtracting 2 pixels for both width and height in my call to setPreferredSize but if this anomaly is due to a graphics driver bug, this isn't a good solution.

Curious if there is a cleaner solution. The code is provided below using JDK 7 64-BIT Windows 7 ...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class JavaExample {

    private static final Color DARK_SQUARE_COLOR = new Color(205, 133, 63);
    private static final Color LIGHT_SQUARE_COLOR = new Color(245, 222, 179);
    private static final int SQUARE_WIDTH = 16;
    private static final int SQUARE_HEIGHT = 16;

    public JavaExample() {
        JFrame frame = new JFrame();        
        frame.add( new JPanel() {
            private static final long serialVersionUID = 1L;

            {
                setPreferredSize(new Dimension(SQUARE_WIDTH * 8, SQUARE_HEIGHT * 8));
            }

            protected void paintComponent( Graphics g ) {
                super.paintComponent(g);
                for(int row = 0; row < 8; row++) {
                    for(int col = 0; col < 8; col++) {
                        g.setColor(getSquareColor(row, col));
                        g.fillRect(col * SQUARE_WIDTH, row * SQUARE_HEIGHT, SQUARE_WIDTH, SQUARE_HEIGHT);
                    }
                }
            }

            private Color getSquareColor(int row, int col) {
                return (row + col) % 2 == 0 ? LIGHT_SQUARE_COLOR : DARK_SQUARE_COLOR;
            }
        });

        frame.pack();
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible( true );
    }

    public static void main(String [] args) {
        new JavaExample();
    }
}
Constantin
  • 1,506
  • 10
  • 16
  • I also added a print statement in paintComponent and it incorrectly shows width and height as 130 x 130 instead of 128 x 128 – Constantin Dec 13 '16 at 11:12

1 Answers1

1

It is not the first time that I witnessed this behaviour and I'm very sure that it is a bug in swing. It always happened when setResizable(false) is called on a JFrame that already has pack() called on.

The only solution I know is to follow this specific order of the following calls:

  1. frame.setResizable(false);
  2. frame.setVisible(true);
  3. frame.pack();
ArcticLord
  • 3,999
  • 3
  • 27
  • 47
  • *"It is not the first time that I witnessed this behaviour and I'm very sure that it is a bug in swing"* You are surely wrong. The frame decorations of a resizable and unresizable window are different sizes. – Andrew Thompson Dec 13 '16 at 12:45
  • @AndrewThompson Never realized that but makes sense. Thanks for clarifying. – ArcticLord Dec 13 '16 at 12:51
  • @Andrew why should that matter? The size of the panels within the frame should dictate the size of the overall application once pack() is invoked. The method setResizable, if called after pack should respect the current size of the contents. This is non-intuitive behavior and surely a bug in my view. – Constantin Dec 13 '16 at 13:16
  • 2
    Might be related http://stackoverflow.com/questions/29189669/unresizable-jframe-pack-error – Constantin Dec 13 '16 at 13:28