0

I'm creating a simple face using GObject class which will use GRect and GOval. I want GRect and GOval to be anchored to the same coordinates for which I described the getWidth() and getHeight() as Instance Variable. I'm not shown any error when I do so, but there is no result on the canvas. I get result only when I describe the getWidth() and getHeight() as local variables. Why are the instance variables' effect not showing up ?

/*
 * This is section 2 problem 2 to draw a face using GRect amnd GOval. The face is     centred in the canvas.
 * PS: The face is scalable w.r.t. canvas.
*/
package Section_2;
import java.awt.Color;
import java.awt.Graphics;

import acm.graphics.GRect;
import acm.program.GraphicsProgram;

/*
 * creates a robot face which is centered in the canvas.
 */
public class RobotFace extends GraphicsProgram{

private static final long serialVersionUID = 7489531748053730220L;

//canvas dimensions for centering
int _canvasWidth = getWidth();
int _canvasHeight = getHeight();
public void run(){

    removeAll();    //to make sure multiple instances of graphic are not drawn during resize as an effect of overriding Java paint method
    //draw objects
    createFace();

}

//currently only createFace() is implemented
/*
 * creates a rect which is centred in the canvas
 */
private void createFace() {

    //canvas dimensions for centering
    //int _canvasWidth = getWidth();
    //int _canvasHeight = getHeight();

    //make the face scalable
    int _faceWidth = _canvasWidth  / 6;
    int _faceHeight = _canvasHeight / 4;
    //to center the face
    int _faceX = (_canvasWidth - _faceWidth)/2;
    int _faceY = (_canvasHeight - _faceHeight)/2;

    GRect _face = new GRect(_faceX , _faceY, _faceWidth, _faceHeight);
    _face.setFilled(true);
    _face.setColor(Color.BLUE);
    add(_face);
}

/*
 * (non-Javadoc)
 * @see java.awt.Container#paint(java.awt.Graphics)
 * to override Java inherited paint method to retain graphic after resizing  
 */
public void paint(Graphics g) {
    this.run();
    super.paint(g);
}    
}

If you uncomment the local variables for getWidth() and getHeight(), you get the Rect , else no effect on the canvas.

3
  • 1
    Most likely getWidth() and getHeight() return 0 when the instance variables are initialized, and when createFace() is called they have the actual value. Commented Mar 28, 2013 at 16:02
  • What happens if you set _canvasWidth and _canvasHeight to hardcoded values (instead of calling the getWidth()/getHeight() methods) ? Do you see the same problem? Commented Mar 28, 2013 at 16:04
  • with hardcoded values it works fine. The issue is with getWidth() and getHeight() only as noted by @mark-rotteveel Commented Mar 28, 2013 at 16:42

3 Answers 3

1

Instance variable shouldn't be initialized outside of the constructor. What might happen is that the getXXX method are invocated before the superclass is fully initialized and so return 0

Edit :

What i was meaning is that you should better initialize the instance variable inside the class constructor to ensure to correctly set up the parent class before calling its method :

 public class RobotFace extends GraphicsProgram{

 //canvas dimensions for centering
 int _canvasWidth =0;
 int _canvasHeight = 0;

 public RobotFace() {
   super();
   _canvasWidth = getWidth();
   _canvasHeight = getHeight();
 }
 [...]

Anyway no garanty here that it will fix the 0 values cause graphics objects often have a particular lifecycle due to display mechanism, so the height and the widht may still not be initialized after constructor call

Sign up to request clarification or add additional context in comments.

5 Comments

I don't entirely agree with your claim, it is perfectly fine to initialize instance variables outside of the constructor as long as they don't depend on the state of the instance itself. In this specific case it seems that they do depend on the state of the instance itself.
Well, let's say it's a good practice which ensures not to encouter this type of case. ;) Good remark anyway
so is there no way I could use getWidth() and getHeight() as instance variable here ?
@AkashKumarSharma Why don't you want to use these methods?
@MarkRotteveel it is just that there is a lot of copy pasting involved in this. I just learned how to use a class, so I'll try to invoke getWidth() in anotehr class and then call them from there and see if that works. You can see ur self how much i copy pasted in [RobotFace] (github.com/panchtatvam/Stanford_CS106A/blob/master/src/…) . long way to go .
0

The problem is that getWidth() and getHeight() = 0 when RobotFace is initialized. Remove from those lines at class level and uncomment them in the createFace method.

int _canvasWidth = getWidth();
int _canvasHeight = getHeight();

1 Comment

yeah ! that's theonly thing working. @gab is right, getWidth() and getHeight() are returning 0. Will use them locally now. thanks.
0

Well I was mistaken to be using getWidth() and getHeight() before the GObject were being initialised and that was making getWidth() return 0. So the only way to make sure that getWidth() gets called within the scope where GObject are getting initiated was to use local getWidth() for every method like createFace(), createMouth(). This program does work but has a lot of copy pasting involved. So in the alternative class RobotFace2 I created GObjects within run() i.e. didn't create new methods for createFace() etc. This way getWidth() had to be typed only once within run() and eyes and mouth GRect's could be anchored to face GRect. RobotFace2 also does work.

RobotFace and RobotFace2

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.