mbdavis
mbdavis

Reputation: 4010

How to get JPanel to fill parent JFrame

I am trying to draw a circle in the center of a window, and I can't seem to get it right, should be really easy! My understanding is that if you set a JPanel as the content pane of a JFrame, the default layout is a flowLayout and that drawing should start from the top left of the screen as 0,0. To try and figure out what's going on I drew a blue background filling the JPanel, but it seems to have a margin like so:

enter image description here

When the window gets smaller than the blue rectangle, the drawing starts to get clipped from the opposite side:

enter image description here

What's going on! Here is my code:

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

public class Test extends JFrame {

    public static void main(String args[])
    {
        Test test = new Test();
        test.Start();
    }

    public void Start()
    {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(500, 500);
        CirclePanel circlePanel = new CirclePanel();
        this.setContentPane(circlePanel);
        this.setVisible(true);
    }

    public class CirclePanel extends JPanel
    {
        private int radius = 200;

        public void paintComponent(Graphics g) {
            g.setColor(Color.blue);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());
            g.setColor(Color.red);
            int diameter = radius * 2;
            g.fillOval(getX(), getY(), diameter, diameter);
        }

        public int getX()
        {
            return (this.getWidth()/2) - radius;
        }

        public int getY()
        {
            return (this.getHeight()/2) - radius;
        }
    }
}

Upvotes: 2

Views: 629

Answers (3)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285405

One big issue, you're unknowingly overriding two critical methods used by the layout managers to position components, the getX() and getY() methods, and thereby you're messing with the JPanel's placement.

So first and foremost, rename these methods so you don't accidentally move the JPanel.

Also, don't forget to call the super's paintComponent method, and avoid calling setSize(). Instead override getPreferredSize on your JPanel, and pack your JFrame.

e.g.,

public int getMyX() {
   return myX;
}

public int getMyY() {
   return myY;
}

For example

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

public class Test extends JFrame {

   public static void main(String args[]) {
      //!! 
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            Test test = new Test();
            test.Start();
         }
      });
   }

   public void Start() {
      this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      // this.setSize(500, 500);
      CirclePanel circlePanel = new CirclePanel();
      setContentPane(circlePanel);
      pack();
      setVisible(true);
   }

   public class CirclePanel extends JPanel {
      private static final int PREF_W = 500;
      private static final int PREF_H = PREF_W;
      private int radius = 200;

      public void paintComponent(Graphics g) {
         super.paintComponent(g); //!!
         g.setColor(Color.blue);
         g.fillRect(0, 0, this.getWidth(), this.getHeight());
         g.setColor(Color.red);
         int diameter = radius * 2;
         g.fillOval(getMyX(), getMyY(), diameter, diameter);
      }

      //!!
      public int getMyX() {
         return (this.getWidth() / 2) - radius;
      }

      //!!
      public int getMyY() {
         return (this.getHeight() / 2) - radius;
      }

      //!!
      @Override
      public Dimension getPreferredSize() {
         if (isPreferredSizeSet()) {
            return super.getPreferredSize();
         }
         return new Dimension(PREF_W, PREF_H);
      }
   }
}

Upvotes: 5

AcademicDuck
AcademicDuck

Reputation: 5

Try using this.add(circlePanel) instead if this.setContentPane(circlePanel) and set the size of the JPanel to be the same size as the JFrame

Upvotes: 0

kiheru
kiheru

Reputation: 6618

The problem is that you're overriding getX() and getY(). Rename those to something else, and your code will work as expected. Also, it's a good idea to turn on compiler warnings for missing @Override annotations, and heed those warnings. (That would have notified the methods override superclass methods).

Upvotes: 3

Related Questions