0

I just don't get this. I want to add Highlight extends JComponent objects to a PdfPage extends JPanel but the Highlight components are simple not painted. I can see that their paint() and paintComponent() methods are getting called in correct order but they do not show. The only thing that fixes my problem is to add:

for(Component component : this.getComponents()) {           
    component.paint(g);         
}

into the PdfPanel.paint() method but this is not how I want to do that. I want PdfPage extends JPanel to render any JComponent I'm adding but not override paint() if possible.

This is how I add Highlight components to PdfPage panels:

for (DatasheetError datasheetError : datasheetErrorList) {

    int pageNumber = datasheetError.getPageNumber();
    Highlight highlight = createErrorHighlight(datasheetError);

    PdfPage pdfPage = pdfPages[pageNumber];     
    pdfPage.add(highlight);
}

This is how PdfPage looks like. Note that I am not using a LayoutManager as I am calling super(null);:

public class PdfPage extends JPanel  {
    private static final long serialVersionUID = 7756137054877582063L;

    final Image pageImage;

    public PdfPage(Image pageImage) {
        // No need for a 'LayoutManager'
        super(null);

        this.pageImage = pageImage;     
        Rectangle bounds = new Rectangle(0, 0, pageImage.getWidth(null), pageImage.getHeight(null));
        this.setBounds(bounds);
        this.setLayout(null);
    }

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

    private void paintPdfPage(Graphics g) {
        // For now transparent background to see if `Highlight` gets painted
        g.setColor(new Color(1.0f, 1.0f, 1.0f, 0.0f));
        g.fillRect(0, 0, getWidth(), getHeight());
    }

}

In Highlight.java you can see that I call this.setBounds(bounds);

public class Highlight extends JComponent {
    private static final long serialVersionUID = -1010170342883487727L;

    private Color borderColor = new Color(0, 0, 0, 0);

    private Color fillColor;

    public Highlight(Rectangle bounds, Color fillColor) {
        this.fillColor = fillColor; 
        this.setBounds(bounds);
    }

    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);

        Rectangle bounds = this.getBounds();

        g.setColor(this.fillColor);
        g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);

        g.setColor(this.borderColor);
        g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height);    
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Stefan Falk
  • 23,898
  • 50
  • 191
  • 378
  • 2
    1. call directly to the variable e.g. myComponent.repaint() instead of loops component.paint(g); 2. overide getPreferredSize instead of Rectangle bounds = this.getBounds();, then use getWeight/Height rahter than bounds.width, bounds.height, 3. for better help sooner post an SSCCE / MCVE, short runnable, compilable – mKorbel Aug 05 '15 at 11:30
  • @mKorbel 1. Like I said in my question I don't want to have that loop in `paint()`. Imho I shouldn't have to call `paint()` or `repaint()` on any `JComponent`I've added. 2. Why? I'm just getting the bounds to just draw a simple rectangle? Why would I override `getPreferredSize()`? It returns correct values already. 3. Agree, I'll see what I can do. – Stefan Falk Aug 05 '15 at 11:35
  • 1. call myVariableName.repaint(), 2. getPreferredSize() returns by default correct coordinates, is implemented in JComponent and LayoutManagers APIs, why the multiple loops if is there a direct way 3. I'll see what I can do. == up to you, maybe it will be good question – mKorbel Aug 05 '15 at 11:43
  • @mKorbel Thank you for your help but it seems it was just a misunderstanding on my side! But thank you for trying to help! – Stefan Falk Aug 05 '15 at 11:45

1 Answers1

1

Looks like problem is coordinate space

protected void paintComponent(Graphics g) {
...
        Rectangle bounds = this.getBounds();

        g.setColor(this.fillColor);
        g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
...
    }

The getBounds() returns the component's rectanle on parent container. So when you can call just g.fillRect(0, 0, bounds.width, bounds.height);

mKorbel
  • 109,525
  • 20
  • 134
  • 319
StanislavL
  • 56,971
  • 9
  • 68
  • 98
  • Goddammit you are right! So the rectangle has just been placed off-screen all the time! Thank you, thank you, thank you this was driving me nuts! – Stefan Falk Aug 05 '15 at 11:42