Xascoria Dung
Xascoria Dung

Reputation: 73

Java Swing window size does not match AWT canvas result

I wanted to draw a rectangle with 80% width and 80% height of the original window in the JPanel.

Here's my driver class

public class driver {
    public static void main(String[] args) {
        System.out.println("test");
        Window myWindow = new Window();
        myWindow.add(new GraphPanel());
        myWindow.settings();
    }
}

Here's my JPanel:

import javax.swing.*;

public class Window extends JFrame {

    private static final int width = 1100;
    private static final int height = 600;

    public void settings(){
        setSize(width,height);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    public static int[] getWindowSize(){
        int[] output = new int[]{width, height};
        return output;
    }
}

and the rectangle canvas:

import java.awt.*;

public class GraphPanel extends Canvas {
    public void paint(Graphics g){
        setBackground(Color.WHITE);
        setForeground(Color.DARK_GRAY);

        int[] windowSize = Window.getWindowSize();

        //Not working as intented
        g.drawRect(windowSize[0]/10, windowSize[1]/10, 8*windowSize[0]/10, 8*windowSize[1]/10);
    }
}

And here's the result, I can't post image so here's a link https://i.sstatic.net/VlQIk.png

As you can see, this is clearly not centered, the height is off by about 30 pixels and width about 20. I have no idea how this happened, so my question is, does anyone know what might have caused this?

Upvotes: 1

Views: 675

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347234

You might want to start by having a quick read of this to get a better understand of why you current approach isn't going to work (the way you expect).

The first thing I would do is change your GraphPanel so it defines it's preferredSize, independent of the window. This way you give control to the layout management system instead.

Next, I would use the actual physical size of the component to base your calculations on

int width = (int) (getWidth() * 0.8);
int height = (int) (getHeight() * 0.8);

I'd also recommend moving the setBackground and setBackground out of the paint method. This will cause a new pain cycle to occur and will make a mess of things.

public class GraphPanel extends Canvas {

    private static final int PREF_WIDTH = 1100;
    private static final int PREF_HEIGHT = 600;

    public GraphPanel() {
        setBackground(Color.WHITE);
        setBackground(Color.DARK_GRAY);
    }

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

    @Override
    public void paint(Graphics g) {
        super.paint(g);

        int width = (int) (getWidth() * 0.8);
        int height = (int) (getHeight() * 0.8);

        int x = (getWidth() - width) / 2;
        int y = (getHeight() - height) / 2;

        //Not working as intented
        g.drawRect(x, y, width, height);
    }
}

I would then update your Window class so it used pack instead of setSize. This will "pack" the window around the content, taking into consideration the frame decorations.

public class Window extends JFrame {

    public void settings() {
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

Although, I'd question the point of extending from JFrame, but I'm getting of topic.

Speaking of which, unless you're intending to high performance graphics which requires you to have complete control over the painting sub system, I'd recommend starting with Swing based components or even JavaFX

Upvotes: 0

Related Questions