-
Notifications
You must be signed in to change notification settings - Fork 0
JFrame's Content Pane
A window has more than just components you'd want to add to it, such as a label for a title, buttons to minimize and close...
-
Because of this,
JFramedesignates aJPanelas the content pane for the window - a pane for the application's content. -
Without understanding content panes, you can experience some strange bugs.
If we added a JButton to the frame, then printed out all the components the JFrame consists of, you would expect to see a JButton.
However...
JFrame frame = new JFrame();
frame.add(new JButton());
for(Component comp : frame.getComponents())
System.out.println(comp.getClass().getSimpleName());
The code above prints JRootPane, not JButton. What's going on?
If we dive into frame.add(Component), we will get our answer:
if(isRootPaneCheckingEnabled())
getContentPane().add(comp, constraints, index);
The documentation for rootPaneCheckingEnabled states:
If true then calls to
addandsetLayoutwill be forwarded to thecontentPane.This is initially false, but is set to true when the
JFrameis constructed.
So not only is it almost always true, but it affects setLayout too!
If we print the components of the content pane using getContentPane(), we will find the JButton.
for(Component comp : frame.getContentPane().getComponents())
System.out.println(comp.getClass().getSimpleName());
BoxLayout is a very simple layout.
BoxLayout layout = new BoxLayout(parent, BoxLayout.X_AXIS);
You specify the parent (component that uses the layout) and specify which axis components should appear on.
So, what happens when we do this?
JFrame frame = new JFrame();
BoxLayout layout = new BoxLayout(frame, BoxLayout.X_AXIS);
frame.setLayout(layout);
frame.add(new JButton());
Shouldn't be an issue, right? Well.. We get an error.
java.awt.AWTError: BoxLayout can't be shared
JFrame "delegated" (passed) the layout to the content pane - the layout was added to the content pane.
However, BoxLayout thinks JFrame is the one using the layout, since we passed it JFrame. But JFrame secretly passed the layout to the content pane, meaning JFrame is not the layout owner.
This causes confusion, resulting in a fail-safe error to prevent visual bugs.
This can be solved by specifying the content pane as the parent for the layout.
JFrame frame = new JFrame();
BoxLayout layout = new BoxLayout(frame.getContentPane(), BoxLayout.X_AXIS);
frame.setLayout(layout);
frame.add(new JButton());
Only manipulate JFrame if you need to really work with the frame. This includes
- Setting actions for the X button
- Setting the title
- Adding menus
- Etc..
For everything else, you should use frame.getContentPane() to work with the content pane directly.