Reputation: 4010
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:
When the window gets smaller than the blue rectangle, the drawing starts to get clipped from the opposite side:
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
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
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
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