Roman Roman - 12 days ago 10
Java Question

What is the relation between ContentPane and JPanel?

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
getContentPane()
) and then containers are, by the construction, included into the
JFrame
(the windows).

I tried two things:


  1. I got rid of the containers. In more details, I added buttons to a panel (instance of
    JPanel
    ) and then I added the panel to the windows (instance of
    JFrame
    ). It worked fine.

  2. I got rid of the panels. In more details, I added buttons directly to the container and then I added the container to the window (instance of
    JFrame
    ).



So, I do not understand two things.


  1. Why do we have two competing mechanism to do the same things?

  2. What is the reason to use containers in combination with the panels (
    JPanel
    )? (For example, what for we include buttons in JPanels and then we include JPanels in the Containers). Can we include
    JPanel
    in
    JPanel
    ? Can we include a container in container?



ADDED:

Maybe essence of my question can be put into one line of code:

frame.getContentPane().add(panel);


What for we put
getContentPane()
in between? I tried just
frame.add(panel);
and it works fine.

ADDED 2:

I would like to add some code to be more clear about what I mean. In this example I use only JPane:

import java.awt.*;
import javax.swing.*;
public class HelloWorldSwing {
public static void main(String[] args) {
JFrame frame = new JFrame("HelloWorldSwing");
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(new JButton("W"), BorderLayout.NORTH);
panel.add(new JButton("E"), BorderLayout.SOUTH);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}


And in this example I use only Content Pane:

import java.awt.*;
import javax.swing.*;
public class HelloWorldSwing {
public static void main(String[] args) {
JFrame frame = new JFrame("HelloWorldSwing");
Container pane = frame.getContentPane();
pane.setLayout(new BorderLayout());
pane.add(new JButton("W"), BorderLayout.NORTH);
pane.add(new JButton("E"), BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}


Both work fine! I just want to know if between these two ways to do things one is better (safer).

Answer

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 Components 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 Components 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.