JustinBlaber
JustinBlaber

Reputation: 4650

Overriding paintComponent twice

This is more of a conceptual question, so it's hard to post a small workable code sample. But, I have a class that overrides paintComponent here:

public abstract class BasePanel extends JPanel {

    ...    

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);       
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                            RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);

        this.standardDraw(drawObjects,g2);
    }   
}

Basically, I'd like this to be the "standard way" this base panel draws if paintComponent is not overridden in a derived class. So, I have a derived class called AspectRatioPanel which I'd like to re-specify how it draws things:

public class AspectRatioPanel extends BasePanel {

    ...

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);       
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                            RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);

        // Get ViewPort Bounding Box to clip
        BoundingBox viewPortBoundingBox = this.getViewPortBoundingBox();

        // Clip to viewport
        g2.setClip((int)viewPortBoundingBox.topLeft.getX(),(int)viewPortBoundingBox.topLeft.getY(),(int)viewPortBoundingBox.getWidth(),(int)viewPortBoundingBox.getHeight());

        this.standardDraw(drawObjectsBuf,g2);
    }   
}

The problem I'm having is the call super.paintComponent(g) in the derived class. I intend for it to be calling paintComponent in JComponent, but it is going through BasePanel first. Is there a better way to approach this problem? I could delete the paintComponent method in BasePanel, but having a standard way of drawing things is useful for me. I also can't seem to call JComponent.paintComponent directly since it's protected. Is there a solution for this? Also, am I doing something conceptually wrong?

Upvotes: 1

Views: 227

Answers (2)

Durandal
Durandal

Reputation: 20069

You could simply not call super.paintComponent(Graphics); by overwriting paintComponent() you have 3 options:

a.) Call super at the beginning of the method; you paint code paints on top of what has been painted by the super class.

b.) Don't call super at all - your paintComponent needs to ensure it paints everything that is needed; if the components is opaque that means you need to paint the entire area the component occupies.

c.) Call super at your convinience; whatever is painted in super appears to be "layered" in sequence where you call it. Makes only sense if the super method doesn't paint the entire area.

If you insist to use paintComponent from a specific class of your inheritance hierarchy as super.paintComponent, regardless of inheritance hierarchy in between, thats also possible:

BasePanel extends JPanel {
     protected final defaultPaintComponent(Graphics g) {
         super.paintComponent(g);
     }
}

Child classes can call "defaultPaintComponent" instead of super.paintComponent, thus bypassing any implementation classes in between in the hierarchy defined (I suggest declaring it final to prevent accidental overwrites).

Upvotes: 1

Sergiy Medvynskyy
Sergiy Medvynskyy

Reputation: 11327

Probably I misunderstood your problem, but I would separate standard and custom painting

public abstract class BasePanel extends JPanel {

...    

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);       
    provideCustomPainting(g);
  }   

  protected void provideCustomPainting(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                        RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);

    this.standardDraw(drawObjects,g2);
  }
}

public class AspectRatioPanel extends BasePanel {
  protected void provideCustomPainting(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                        RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);

    // Get ViewPort Bounding Box to clip
    BoundingBox viewPortBoundingBox = this.getViewPortBoundingBox();

    // Clip to viewport
    g2.setClip((int)viewPortBoundingBox.topLeft.getX(),(int)viewPortBoundingBox.topLeft.getY(),(int)viewPortBoundingBox.getWidth(),(int)viewPortBoundingBox.getHeight());

    this.standardDraw(drawObjectsBuf,g2);
  }
}

Upvotes: 4

Related Questions