Yonshoku
Yonshoku

Reputation: 117

Why is JPanel size is wrong?

There is constructor of class extending JFrame:

import java.awt.*;
import javax.swing.*;

public class ChessFrame extends JFrame {
    public ChessFrame () {
        setSize(520, 520);
        setResizable(false);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(1, 1));

        // Add components
        getContentPane().add(new Board());
        pack();
        setVisible(true);
    }
}

And class extending JPanel:

import javax.swing.*;

public class Board extends JPanel {
    public Board() {
        setSize(new Dimension(520, 520));
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.fillRect(0, 0, 520, 520);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(520, 520);
    }
}

As a result rectangle smaller then 520x520. enter image description here

Size of black rectangle is about 496x510. There is more:

  1. getWidth() and getHegiht() written inside the Board class, returns 0 and 0 (so size of this JPanel into JFrame is 0x0)
  2. If I remove pack(), size of frame becomes 496x510 (black rectangle size)

It's actually copypaste of official java tutorial: https://docs.oracle.com/javase/tutorial/uiswing/painting/step2.html.

Do I do something wrong or it's something related with java? If it's second, why does this happen? Any help would be appreciated.

Upvotes: 2

Views: 852

Answers (1)

Andrew Thompson
Andrew Thompson

Reputation: 168845

enter image description here

This example only tries to establish the panel size once the frame (and panel) are visible on-screen. It returns the exact size (300 pixels) set in the code.

import java.awt.*;
import javax.swing.*;

public class ChessBoard extends JPanel {
    
    int size = 300;
    JLabel sizeLabel = new JLabel();

    ChessBoard() {
        setBackground(Color.CYAN);
        setLayout(new GridBagLayout());
        add(sizeLabel);
    }
    
    public void showSize() {
        sizeLabel.setText(String.format("%1sx%1s", getWidth(), getHeight()));
    }
    
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(size,size);
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            ChessBoard cb = new ChessBoard();
            
            JFrame f = new JFrame(cb.getClass().getSimpleName());
            f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            f.setLocationByPlatform(true);
            
            f.setContentPane(cb);
            f.pack();
            f.setMinimumSize(f.getSize());
            
            f.setVisible(true);
            // delay showing size until app. is on-screen
            Runnable r1 = cb::showSize;
            SwingUtilities.invokeLater(r1);
        };
        SwingUtilities.invokeLater(r);
    }
}

Upvotes: 2

Related Questions