I found one example in which buttons are added to panels (instances of JPanel
) then panels are added to the the containers (instances generated by getCont
interesting: jframe.setBackground(color)
does not work for me, but jframe.getContentPane().setBackground(color)
works.
The history and mechanics of this are also discussed in some detail at this leepoint article. Note in particular:
getContentPane()
returns aContainer
object. This isn't really a plainContainer
object, but is actually aJPanel
! This is aContainer
as a consequence of the hierarchy. So if we get the predefined content pane, it turns out it's actually aJPanel
, but we really can't take advantage of the functionality that was added byJComponent
.
and
They defined
add()
methods inJFrame
which simply call the correspondingadd()
methods for the content pane. It seems strange to add this feature now, especially since many layouts use multiple nested panels so you still have to be comfortable with adding directly to aJPanel
. And not everything you want to do with the content pane can be done through calls to theJFrame
.
I believe the reason is because Swing was built off of AWT, and Container is a top level AWT object. It really isn't the greatest design choice, though, since you generally don't want to mix AWT (heavyweight) objects with Swing (lightweight).
I think the best way to handle it is to always cast the contentPane to a JPanel.
JPanel contentPanel = (JPanel)aFrame.getContentPane();
It is all written in the last version API doc that JFrame.add() (nowerdays) is enough.
You may compare to older Java versions here.
It's not two competing mechanisms - a JPanel
is a Container
(just look at the class hierarchy at the top of the JPanel javadocs). JFrame.getContentPane()
just returns a Container
to place the Component
s that you want to display in the JFrame
. Internally, it's using a JPanel
(by default - you can change this by calling setContentPane()
) As for why it's returning a Container
instead of a JPanel
- it's because you should program to an interface, not an implementation - at that level, all that you need to care about is that you can add Component
s to something - and even though Container
is a class rather than an interface - it provides the interface needed to do exactly that.
As for why both JFrame.add()
and JFrame.getContentPane().add()
both do the same thing - JFrame.add()
is overridden to call JFrame.getContentPane().add()
. This wasn't always the case - pre-JDK 1.5 you always had to specify JFrame.getContentPane().add()
explicitly and JFrame.add()
threw a RuntimeException
if you called it, but due to many complaints, this was changed in JDK 1.5 to do what you'd expect.
Good question. I found it helpful to understand that "Swing provides three generally useful top-level container classes: JFrame
, JDialog
, and JApplet
. ... As a convenience, the add method and its variants, remove and setLayout have been overridden to forward to the contentPane as necessary."—Using Top-Level Containers