Can I override getGraphics() in the Canvas class?

Hi,

I’ve just spent the last few hours browsing trough Java’s class library to see if I could figure out how it all (or at least parts of it…) works. I would like to override the getGraphics() method in java.awt.Canvas (inherrited from Component) to return a Graphics object from my buffer strategy instead. Under which conditions can this be done. I.e. what calls do I have to make in my override method so everything (graphics wise) still works as expected?

Here is the source code from java.awt.Component:

/**
 * Creates a graphics context for this component. This method will
 * return <code>null</code> if this component is currently not
 * displayable.
 * @return a graphics context for this component, or <code>null</code>
 *             if it has none
 * @see       #paint
 * @since     JDK1.0
 */
public Graphics getGraphics()
{
      if (peer instanceof LightweightPeer)
      {
            // This is for a lightweight component, need to
            // translate coordinate spaces and clip relative
            // to the parent.
            if (parent == null)
                  return null;
            Graphics g = parent.getGraphics();
            if (g == null)
                  return null;
            if (g instanceof ConstrainableGraphics)
            {
                  ((ConstrainableGraphics) g).constrain(x, y, width, height);
            }
            else
            {
                  g.translate(x, y);
                  g.setClip(0, 0, width, height);
            }
            g.setFont(getFont());
            return g;
      }
      else
      {
            ComponentPeer peer = this.peer;
            return (peer != null) ? peer.getGraphics() : null;
      }
}

If both Component and Canvas can be said not to be LightweightPeer:s we can rule out most of the code. Neither of the two implement the LightweightPeer interface. If it isn’t some internal stuff of course.

Best Regards,

Johan Tibell

You shouldn’t be worrying about Peers, just override the getGraphics() method so it returns the graphics context of your back buffer.

So I could do this (strategy is just a reference to BufferGraphics)?

public Graphics getGraphics()
{
      if (strategy == null)
      {
            createBufferStrategy(2);
            strategy = getBufferStrategy();
      }
            
      return strategy.getDrawGraphics();
}

What happends if it gets called during a frame.add(canvas), a frame.pack() or a frame.setVisible(true)? That was my original problem. getGraphics() got called by Java at some time when the buffer couldn’t be created, probably because the canvas wasn’t visible or had a size 0. Should I check if it’s visible? How?

EDIT: I changed the getGraphics() to the code above and now nothing gets drawn…

Also, to try some light on the issue, I tried checking isLightweight() on the canvas the time it was visible and it returned false. By reading the API I found this:

[i]isLightweight
public boolean isLightweight()A lightweight component doesn’t have a native toolkit peer. Subclasses of Component and Container, other than the ones defined in this package like Button or Scrollbar, are lightweight. All of the Swing components are lightweights.
This method will always return false if this component is not displayable because it is impossible to determine the weight of an undisplayable component.

Returns:
true if this component has a lightweight peer; false if it has a native peer or no peer
Since:
1.2
See Also:
isDisplayable()[/i]

From this I draw the conclussion that Canvas itself isn’t a LightweightPeer and that Canvas has a peer object.

Solution
After a deeper investigation of the problem I found out why it isn’t possible to return a offscreen buffer in a getGraphics call. The buffer strategy calls getGraphics to receive the canvas’s (or component’s) Graphics object so it can be used to draw the offscreen buffer to the screen. Changing getGraphics to return an offscreen resulted in the buffer strategy drawing on its own back buffer when trying to blit to the screen.

  • Johan