7

I'm playing around with Java Swing and i'm really confused when comes to JPanel vs JComponent. According to CoreJava Vol 1 (cay horstmann):

Instead of extending JComponent, some programmers prefer to extend the JPanel class. A JPanel is intended to be a container that can contain other components, but it is also possible to paint on it. There is just one difference. A panel is opaque, which means that it is responsible for painting all pixels within its bounds. The easiest way to achieve that is to paint the panel with the background color, by calling super.paintComponent in the paintComponent method of each panel subclass:

class NotHelloWorldPanel extends JPanel {
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    . . . // code for drawing will go here
  }
}

I know what opaque is. What does he meant by 'A panel is opaque .. responsible for painting all pixels within its bound'? If I read it correctly it says a panel will paint its own areas within its boundaries .. Doesn't JComponent does that too?

Bottom line is I couldn't see the difference between JPanel and JComponent. Is there a simple examples where I can REALLY see it?

Any help is appreciated

DT7
  • 1,615
  • 12
  • 25
yapkm01
  • 2,905
  • 6
  • 34
  • 52
  • JLabel is a JComponent that renders text, the whole box that wraps the text is transparent. As you said, JPanel are JComponents that are meant to be containers, but there are JComponents that does not allow other elements inside, like the JLabel, JMenuItem.. some use setComponent, some use addComponent (containers). So JLabel is an example of a JComponent that will not paint the whole box. – porfiriopartida Oct 01 '13 at 17:42
  • DO keep in mind, that `JPanel` is not always `Opaque` as it is already mentioned in Java Tutorials cited [here](http://docs.oracle.com/javase/tutorial/uiswing/painting/problems.html) __(Problem 3, point 1) JPanel is not opaque for GTK+ Laf)__ . So it's always best to set it explicitly :-) – nIcE cOw Oct 01 '13 at 18:17
  • @nIcEcOw I would say it's best to set it explicitly if the correctness of the class depends on it. Otherwise it's best to leave it to the Laf. After all that's what look and feel is for. – Cruncher Oct 01 '13 at 19:17
  • @Cruncher : It depends on what you can leave on to the LaF, like Nimbus itself is quite buggy. So I will prefer not to use such Look And Feels, which might can give obnoxious behaviour :-) – nIcE cOw Oct 01 '13 at 19:21
  • 1
    @nIcEcOw I think we're arguing the same point :) – Cruncher Oct 01 '13 at 19:29

1 Answers1

6

A JComponent is not required to paint all pixels in it's bound. It may leave some transparent so you can see components behind it.

A JPanel is required to paint all pixels.

Of course if you don't call the super.paintComponent(..) method in either case, they're going to be more or less equivilent, as you then throw out the guarentee that the JPanel will paint the entire panel.

In short, the difference lies in the methods that already exist(namely paint component).

EDIT:

Example of a ball class implemented with a JComponent would look something like this:

(This would not work with a JPanel, as the JPanel is opaque, and the ball would have a square background. You could not call super.paintComponent, but as a general rule you always should, or you break what the component really is. If I pass a JPanel into something, they expect it to be a JPanel, not a JPanel hacked to behave like a JComponent)

public class Ball extends JComponent
{
    public Ball(int x, int y, int diameter)
    {
        super();
        this.setLocation(x, y);
        this.setSize(diameter, diameter);
    }

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.setColor(Color.red);
        g.fillOval(0, 0, width, height);
    }
}
Cruncher
  • 7,241
  • 1
  • 26
  • 62
  • 1
    i need examples .. i just cant see it. Picture speaks a thousand words – yapkm01 Oct 01 '13 at 17:44
  • Edited with an example – Cruncher Oct 01 '13 at 17:47
  • Thx. I'm gonna try it out. Will let you know. Appreciate much! – yapkm01 Oct 01 '13 at 17:57
  • @yapkm01 Note, with this particular example, I think you need to have a null layout on whatever container is holding this in order for the passed location to work properly. Not a layout expert though – Cruncher Oct 01 '13 at 17:58
  • I tested with Ball extends JPanel and also JComponent and they both behaves the same. No difference – yapkm01 Oct 01 '13 at 18:33
  • @yapkm01 The background of your frame may be same as the background colour of your panel, giving you the appearance of transparency. Try changing the background colour of your frame, and then you'll probably notice it. – Cruncher Oct 01 '13 at 19:06
  • I'm getting frustrated cos' i'm having difficulty understanding the basics of jcomponent/jpanel. Please see my other questions. Thx – yapkm01 Oct 01 '13 at 19:22
  • So even the JFrame behaves like JComponent. What i meant is it uses the graphic class for painting, right? Reason i ask cos' on the frame constructor i use setBackground(Color.green) to the frame but nothing happens. Why have this setBackground(Color) when it uses the graphic class to fill in or paint the color? – yapkm01 Oct 01 '13 at 20:02
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/38451/discussion-between-cruncher-and-yapkm01) – Cruncher Oct 01 '13 at 20:04
  • I think i get it. For frame, i need to get the contentpane and then set the background color. Thx – yapkm01 Oct 01 '13 at 20:24