20

hello I'm new in java programming, and i need someone explaining me these lines of code:

 public class drawpanel extends JPanel
 {
     public void paintComponent(Graphics g)
     { 
         super.paintComponent(g);
         ...
     }
 }

I dont understand the line public void paintComponent(Graphics g): why do i have to declare that function like that if it's predefined in JPanel?

And this line super.paintComponent(g): I dont understand it at all. Thank you for your help.

rekaszeru
  • 19,130
  • 7
  • 59
  • 73
jose gabriel
  • 754
  • 2
  • 8
  • 21

3 Answers3

53

The Basic Structure:

The extends keyword means that DrawPanel inherits from JPanel. In other words, DrawPanel "is a" JPanel. As such, it can override its methods (the ones that aren't marked final). You might want to do that for several reasons. For example, you might want to gain access to the panel's Graphics class, which you could use to draw a circle on the panel, or a bar graph, or a string of text.

If you don't override any methods, then when you extend JPanel you get something like this:

public class DrawPanel extends JPanel {
    //TODO not much
}

However, that's not very useful ...unless you just don't like the name JPanel and want to call it AwesomePanel instead (note: don't do that). If that's all you have, you're better off just creating an instance of JPanel, like this: JPanel drawPanel = new JPanel();


paintComponent:

The purpose of extending a JPanel is to override the paintComponent method. The JPanel is invisible until you override paintComponent (note: being invisible is what makes it a useful container for buttons and other components). You are right that the paintComponent method is pre-defined (in the JComponent class if you were wondering), but all that method does is make an empty JPanel. If you want to draw something on the panel, then you need to override it, like this:

public class DrawPanel extends JPanel {
    @Override public void paintComponent(Graphics g) { // <-- HERE!
        //TODO draw stuff
    }
}

note: the @Override part is not strictly necessary but it's good practice to include it because it reduces the number runtime errors and improves code readability

You now have access to the Graphics object g for the panel. Graphics is a helper class that allows you to draw things on the panel, like this:

public class DrawPanel extends JPanel {
    @Override public void paintComponent(Graphics g) {
        g.drawOval(50, 50, 50, 50); // <-- draws an oval on the panel
    }
}

super.paintComponent:

helpful metaphor (that I just made up): The JPanel is the canvas, the Graphics object is your paintbrush, and super.paintComponent(g) is your eraser. (Also, JFrame is your easel.)

So super.paintComponent(g) invokes the paintComponent method from the superclass of JPanel (the JComponent class) to erase whatever is currently drawn on the panel. This is useful for animation.

For example, consider drawing an analog clock on the panel. You need to refresh it every second, so each second you have to erase the previous clock and redraw the clock, adjusting the second hand. If you don't invoke super.paintComponent(g) before redrawing the clock, it will just keep drawing new clocks on top of the old clocks and in 60 seconds what you'll have is just a filled in circle, more or less.

Only one more thing to remember: always call super.paintComponent(g) first in the paintComponent method, like this:

public class DrawPanel extends JPanel {
    public void paintComponent(Graphics g) {
        super.paintComponent(g); // <-- HERE!
        g.drawOval(50, 50, 50, 50);
    }
}

That's it. Feel free to contact me.


Example:

I created a simple example that uses these concepts to display a string of text on a panel (which is placed inside a frame). Save in your IDE as TestPanel.java.

import java.awt.*;
import java.util.*;
import javax.swing.*;

/**
 * A frame containing a panel that is sometimes red and sometimes 
 * blue. Also, it displays the word to go with it. 
 * 
 * Inspired by www.sometimesredsometimesblue.com.
 *
 */
public class TestPanel extends JPanel {

    private Random random = new Random();
    private boolean isRed;
    private String s = "";

    public TestPanel() {
        //randomly determine whether the background should be red
        isRed = random.nextBoolean();

        //set the background to blue
        setBackground(Color.BLUE);
        s = "BLUE";

        //if 'isRed' is true, set the background to red
        if (isRed) {
            setBackground(Color.RED);
            s = "RED";
        }
    }

    @Override 
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        //write either "RED" or "BLUE" using graphics
        g.setColor(Color.WHITE);
        g.setFont(new Font("serif", Font.BOLD, 60));
        g.drawString(s, getWidth() / 2 - g.getFontMetrics().stringWidth(s) / 2,
                getHeight() / 2 + g.getFontMetrics().getHeight() / 2);
    }

    //main method: create an instance of TestPanel and output it on a JFrame
    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setSize(500, 500);
        f.setTitle("Sometimes Red, Sometimes Blue");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(new TestPanel());
        f.setVisible(true);
    }
}
TheBlackKeys
  • 852
  • 1
  • 9
  • 15
  • 5
    -1 a) invisible is wrong b) subclassed must guarantee to comply to their contract opacity: if opaque (default) they must fill their entire content area with a fully opaque color, if false they are free to not fill the entire region. super.paintComponent is the easiest way to comply to the contract (alternatively, you could manually fill it, depending on opacity setting). An override that unconditionally only fills an arbitrary portion (as yours in the paragraph titled paintComponent) is _invalid_ – kleopatra Sep 26 '12 at 15:41
  • 1
    Awesome explanation TheBlackKeys! This helped me understand a lot – NoobCoderChick Feb 28 '16 at 03:53
2

paintComponent() is a method originally defined in abstract class JComponent. Components that extend JComponent directly indirectly (if exposed) have the option to override paintComponent(). the call to super.paintComponent(g) calls the super class's implementation of paintComponent() (in your case it's JPanel's). You would want to override paintComponent() if you want to do other stuff with Graphics g besides what JPanel already does.

Bala R
  • 107,317
  • 23
  • 199
  • 210
  • but what does paintcomponent() actually do in those lines??? can you give me some link to a tutorial so i can know how to use it. – jose gabriel Mar 27 '11 at 00:57
  • @jose your paintComponent() is doing noting or at least nothing is show besides calling the base class's `paintComponent()`. After calling `super.paintComponent(g)` , you could do other stuff; for instance `g.drawString("hello world!", 10 ,10 );` – Bala R Mar 27 '11 at 01:01
  • mmm soo if i dont call the superclass paintcomponent() then i cant make changes in graphics like drawing a line or any shape?? – jose gabriel Mar 27 '11 at 01:09
  • do you know any link or book wich can help me with java graphics from the beginning???? – jose gabriel Mar 27 '11 at 01:10
  • the super class's paintComponent() does stuff to draw the panel and you might not want to skip calling it is most cases. You should add the logic to draw whatever you need after the call to `super.paintComponent(g)` . – Bala R Mar 27 '11 at 01:12
  • check out this post http://java.sun.com/products/jfc/tsc/articles/swing2d/index.html – Bala R Mar 27 '11 at 01:14
  • thank you very much. another question: in java can i write the functions prototypes and then declare those functions outside the class like c++???? – jose gabriel Mar 27 '11 at 01:17
  • not in regular classes. Look up abstract class and interfaces for java – Bala R Mar 27 '11 at 01:20
1

You only need to define paintComponent() in your class if you want to change the way your component if being drawn. In your custom implementation you need to call super.paintComponent(g); i.e. a base class version of paintComponent(), because it does some necessary work to prepare component for drawing.

pajton
  • 15,828
  • 8
  • 54
  • 65