Java Swing - JPanel vs JComponent
Asked Answered
F

1

8

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

Fidelity answered 1/10, 2013 at 17:32 Comment(5)
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.Khalif
DO keep in mind, that JPanel is not always Opaque as it is already mentioned in Java Tutorials cited here (Problem 3, point 1) JPanel is not opaque for GTK+ Laf) . So it's always best to set it explicitly :-)Mokpo
@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.Receive
@Receive : 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 :-)Mokpo
@nIcEcOw I think we're arguing the same point :)Receive
R
7

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);
    }
}
Receive answered 1/10, 2013 at 17:39 Comment(10)
i need examples .. i just cant see it. Picture speaks a thousand wordsFidelity
Edited with an exampleReceive
Thx. I'm gonna try it out. Will let you know. Appreciate much!Fidelity
@Fidelity 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 thoughReceive
I tested with Ball extends JPanel and also JComponent and they both behaves the same. No differenceFidelity
@Fidelity 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.Receive
I'm getting frustrated cos' i'm having difficulty understanding the basics of jcomponent/jpanel. Please see my other questions. ThxFidelity
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?Fidelity
let us continue this discussion in chatReceive
I think i get it. For frame, i need to get the contentpane and then set the background color. ThxFidelity

© 2022 - 2024 — McMap. All rights reserved.