Java drawRect() method has weird/wrong sizing

alekala :

So, I'm trying to draw a rectangle on a JPanel (Rect), that's then added to my main JFrame. The rectangle is supposed to be in the middle of my window, but instead it's outside the window.

Things I've tried:

  • Adding a JPanel to JFrame and then adding Rect to the JPanel, no changes.
  • Setting JFrames layout to null, rectangle disappears nowhere to be seen.

Relevant code:

Main.java

package sudoku_solver;

public class Main
{
    public static void main(String[] args)
    {
        int[][] board = Board.getBoard();
        Solver solver = new Solver(board);
        Interface gui = new Interface();

        gui.createFrame();
        gui.drawGrid(board);

        solver.solve();
        solver.print();
    }
}

Interface.java

package sudoku_solver;

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

public class Interface
{
    private static class Rect extends JPanel
    {
        private static final long serialVersionUID = 1L;

        int x;
        int y;
        int rectWidth;
        int rectHeight;
        Color color;

        public Rect(int _x, int _y, int _rectWidth, int _rectHeight, Color _color)
        {
            x = _x;
            y = _y;
            rectWidth = _rectWidth;
            rectHeight = _rectHeight;
            color = _color;
        }

        @Override
        protected void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;                                                                           
            g2d.drawRect(x, y, rectWidth, rectHeight);
            g2d.setColor(color);
        }
    }

    static JFrame frame;
    static int windowWidth = 580;
    static int windowHeight = 580;
    static int cellSize = windowWidth / 9;

    public void createFrame()
    {
        frame = new JFrame("Sudoku");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(windowWidth, windowHeight);
        frame.setVisible(true);
    }

    public void drawGrid(int[][] bo)
    {
        drawBorder();
    }

    private static void drawBorder()
    {
        Rect rect = new Rect(20, 20, windowWidth - 20, windowHeight - 20, Color.black);
        frame.add(rect);
    }
}

Output:

Output I'm getting

Tried finding other people with the same problem but couldn't find any. Thanks!

camickr :

The problem is that you are trying to control the size of the frame. That is NOT how Swing works. Remember the frame size includes the titlebar and the borders. So the size of the panel added to the frame will NEVER be the same size as the frame.

Instead you control the size of the components added to the frame. Then the frame will be size properly based on these components.

static int windowWidth = 580;
static int cellSize = windowWidth / 9;

Why would you ever pick a width of 580. How will you ever get the cell sizes to be equal since 9 does not divide equally into 580.

So instead you should specify your cell size. Then in the panel you multiply by 9 to get the preferred size of the panel.

Rect rect = new Rect(20, 20, windowWidth - 20, windowHeight - 20, Color.black);

Also, don't hardcode the value 20 in 4 different places. Again, you might have a parameter to the class line "borderSize". Then internally you use this value.

So the parameters for your Rect class might look something like: public Rect(int cellSize, int borderSize, Color _color) Now you need to implement the getPreferredSize() method of you class so the component can calculate its own preferred size. Something like:

@Override
public Dimension getPreferredSize()
{
    int size = (cellSize * 9) + (borderSize * 2);
    return new Dimension(size, size);
}

Now when you do your custom painting all the painting is done relative to the panel. Something like:

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;                                                                           
        int size = (cellSize * 9);
        g2d.drawRect(borderSize, borderSize, size, size);
        g2d.setColor(color);
    }

So when you create an instance of the class you would use:

 public void createFrame()
{
    Rect rect = new Rect(50, 20, Color.black);
    frame = new JFrame("Sudoku");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(rect);
    frame.pack();
    //frame.setSize(windowWidth, windowHeight);
    frame.setVisible(true);
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=393477&siteId=1