2

I have a JComponent subclass that I am using to draw shapes onto my screen. In the constructor, I am trying to set ballX and ballY to half of the X and Y size values of the JComponent, and I think I am doing it wrong. I have looked this up a lot now, and cannot find a remedy. The code is as follows. Please bear in mind that this is my first real Swing/Graphics2D venture.

public class PongCanvas extends JComponent {
//Vars to hold XY values and Dimension values.

    private int batXDim, batYDim;
    private int b1X, b1Y;
    private int b2X, b2Y;
    private int ballRad, ballX, ballY;

    public PongCanvas() {//Instantiate vars.
        batXDim = 20;
        batYDim = 100;

        b1X = 0;
        b1Y = 0;

        b2X = 0;
        b2Y = 0;

        ballRad = 20;
        ballX = getWidth() / 2;
        ballY = getHeight() / 2;
    }

    public void paint(Graphics g) {//Main paint Method.
        //Cast Graphics to Graphics2D.
        Graphics2D g2 = (Graphics2D) g;
        //Enable antialiasing.
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        //Draw background.
        g2.setPaint(Color.black);
        g2.fillRect(0, 0, getWidth(), getHeight());
        //Draw ball.
        g2.setPaint(Color.white);
        g2.fillOval(ballX, ballY, ballRad, ballRad);
        //Draw bat 1.
        g2.fillRect(b1X, b1Y, batXDim, batYDim);
        //Draw bat 2.
        g2.fillRect(b2X, b2Y, batXDim, batYDim);
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Jack H
  • 2,440
  • 4
  • 40
  • 63
  • 3
    "Swing programs should override `paintComponent()` instead of overriding `paint()`."—[Painting in AWT and Swing: The Paint Methods](http://java.sun.com/products/jfc/tsc/articles/painting/index.html#callbacks). – trashgod Nov 05 '11 at 02:19

2 Answers2

5

Override getPreferredSize() in your JComponent to return your preferred size, and start with half the width and height of that Dimension. To the same end, this KineticModel invokes setPreferredSize() in DisplayPanel.

Addendum: By way of explanation, your current approach fails because the results from getWidth() and getHeight() are invalid until validate() has been called on the enclosing container, typically as the result of pack().

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I'm sorry, I'm not sure I understand exactly what you mean. – Jack H Nov 05 '11 at 03:09
  • Update your example by overriding the two methods, `paintComponent()` and `getPreferredSize()`. The annotation `@Override` will prove helpful. – trashgod Nov 05 '11 at 03:28
  • Ok, thanks. I shall make the changes once my dev machine is up and running again (keep getting kernel panics). – Jack H Nov 10 '11 at 18:34
2

I agree with trashgod's answer. (+1)

Move the ballX and ballY in the paintComponent(g) like this

if (ballX==0 && ballY==0) {
    ballX = getWidth()/2;
    ballY = getHeight()/2;
}
StanislavL
  • 56,971
  • 9
  • 68
  • 98
  • +1 for suggesting a [sentinel value](http://en.wikipedia.org/wiki/Sentinel_value). Of course, `(0,0)` then becomes the entrance to a kind of wormhole! I often use `Point p;` and later check `if (p == null)` to initialize the starting point. – trashgod Nov 05 '11 at 17:22