Steve P.
Steve P.

Reputation: 14699

Relationship between paint, paintComponent, repaint, etc

The paint method:

Invoked by Swing to draw components. Applications should not invoke paint directly, 
but should instead use the repaint method to schedule the component for redrawing.

This method actually delegates the work of painting to three protected methods: 
paintComponent, paintBorder, and paintChildren. They're called in the order listed 
to ensure that children appear on top of component itself. Generally speaking,
the component and its children should not paint in the insets area allocated to the
border. Subclasses can just override this method, as always. A subclass that just 
wants to specialize the UI (look and feel) delegate's paint method should just 
override paintComponent.

Parameters:
    g the Graphics context in which to paint

public void paint(Graphics g)

I've read many times not to override paint(), but to override paintComponent() instead. As seen above, the documentation also suggests to override paintComponent() if you want to specialize the UI.

So, I wanted to trace through the code to see why this is so.

 protected void paintComponent(Graphics g) 
 {
     if (ui != null) 
     {
         Graphics scratchGraphics = (g == null) ? null : g.create();

         try 
         {
             ui.update(scratchGraphics, this);
         }
         finally 
         {
             scratchGraphics.dispose();
         }
     }
 }

There are many methods to trace through, but for conciseness, here's update():

public void update(Graphics g, JComponent c) 
{
    if (c.isOpaque()) 
    {
        g.setColor(c.getBackground());
        g.fillRect(0, 0, c.getWidth(),c.getHeight());
    }

    paint(g, c);
}

An overloaded version of paint() is called, and paint(), itself, calls paintComponent(). So, I guess I'm just trying to figure out what's going on here exactly. I'm very new to Swing; there are a lot of classes and it's pretty difficult to trace through all of them, especially with my limited knowledge of using GUIs, in general.

Are these methods constantly calling each other, thereby giving the illusion of an image on the screen? If so, why does it matter so much if you override paint() instead of paintComponent? I imagine that my logic is in some way flawed or lacking, considering that for applications, the documentation advises against invoking paint() directly, and instead suggests to invoke repaint(). So, basically, I'm just trying to get some insight into the overall relationship between paint(), paintComponent(), repaint(), etc.

Upvotes: 3

Views: 1214

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347184

Firstly take a look at...

The second should be compulsory reading for all Swing developers.

paint is (within the context of this question) the top level method called (update is actually called first, which just forwards to paint) when the RepaintManager wants a component to be painted.

paint is responsible for (amongst other things) calling paintComponent, paintBorder and paintChildren. If you're not careful you could compromise your components ability to paint. So if you HAVE to override paint, make sure you are calling super.paint.

It's important to note, the if a child component is updated, the parent component may not be repainted, so it don't try and use paint to provide overlays for your component.

paintComponent is responsible for painting the "background" of the component. This basically delegates to the look and feel.

In the case of something like JPanel, it will fill the background with the background color (if set to opaque). In the case of something like JTable, it will paint the rows, columns and cell values.

It is very important to ALWAYS call super.paintComponent, especially when dealing with transparent components.

repaint will make a request to the RepaintManager which may consolidate the paint requests so as to reduce the actual number of paint events that are raised. This helps improve performance.

The important thing to note here is that you don't control the paint process, so don't try, work with it instead.

Your paint method is also expected to run quickly, so avoid time consuming operations, like loading resources, or compound loops where possible. If you can, create backing buffers and paint those instead

ps- Paint is fun ;)

Upvotes: 2

Related Questions