I am researching about AWT as Frame, JFrame and I saw object Contianer as parent of them but I wonder that can I use container object as Frame or JFrame, below is my code but it's not working:
public class icontainer {
public static void main(String[] args) {
Container icon= new Container(); // new JFRAME();
icon.setSize(300,300);
icon.setLocation(300, 300);
icon.setVisible(true);
}
}
Why don't we use icon = new Container() instead JFrame?
That is not how inheritance works.
A Container is a base class that does not much more but keeping track of its children. And that is it. Its not a window itself.
From the Javadoc:
A generic Abstract Window Toolkit(AWT) container object is a component that can contain other AWT components.
Components added to a container are tracked in a list. The order of the list will define the components' front-to-back stacking order within the container. If no index is specified when adding a component to a container, it will be added to the end of the list (and hence to the bottom of the stacking order).
But that is it. There is no mention of a window anywhere. It doesn't display anything on its own. It is displayed in something else.
A JFFrame on the other hand is a window (it literally inherits from java.awt.Window via java.awt.Frame).
From the Javadoc of java.awt.Frame:
A Frame is a top-level window with a title and a border.
And then there are some details about how the Frame layouts the contents etc.pp, and how the window decorations should look like and behave, especially wrt. WindowEvents like WINDOW_CLOSING. Those are things that are all only present in Frames, not Containers.
And if you go down to JFrame, you get some specialized handling of e.g. the content pane to make it work better with the JFC/Swing component architecture.
Container window = new Container();
This is code you can write, but nearly useless. In order for the container to actually be displayed on screen, it still needs to be put into a window.
Container window = new JFrame();
You can do that, because JFrame is a subclass of container, and thus is assignment-compatible to Container.
However, you lose the ability to call any methods introduced by java.awt.Window, java.awt.Frame or javax.swing.JFrame on the container -- because those don't exist on Container.
You should use a JFrame or Frame, because a Container of its own is not a "Window" that is displayed to the User.
I do not recommend it, but you could store your JFrame or Frame as a Container like this:
Container icon = new JFrame();
icon.setSize(300,300);
icon.setLocation(300, 300);
icon.setVisible(true);
Related
I am now writing code simple GUI that's for start the game window. I only need Do you want to start game message and start button on the window. But I have a confusing concepts for the JFrame and JPanel. Actually, I thought I need to add JPanel to JFrame to add the other components such as JLabel, JButton,...etc. But I realized I don't actually need JPanel. I can just add the components simply use add(button), add(label) to JFrame. So why I need JPanel. And I think JFrame doesn't need JPanel but JPanel need JFrame. Am I understand correctly?
No, not always. A simple graphical user interface may be implemented by just adding components "directly" to a JFrame. But in order to get more flexibility, you would always use JPanels. For example, to employ different layouts in different parts of the GUI, to group certain components together, etc.
A JFrame is backed by a JRootPane, a part of which is a contentPane.
(image from Oracle Javadoc)
When you add components to a JFrame, you are really adding them to the content pane, e.g.: frame.getContentPane().add(Component).
A JFrame is a common starting scene of a Swing GUI application, while a JPanel is intended to be put in another scene (container). Since both content pane and a JPanel inherit from the same class (Container) you may use them in a similar manner, as far as adding components to them goes.
Do I need JPanel always?
No. Well, unless you need a Swing GUI. Then yes.
Another answer replied words to the effect. "No, you can add components direct to a frame" What they missed was that components added to a JFrame are added to the content pane (automatically). The content pane is a JPanel.
Having said that:
I (and many others) would recommend designing an app based around a main content panel, then adding that panel to a top-level container as needed. The top level container might be a JFrame, JWindow, JDialog, JOptionPane ..
What prompted the question? A JPanel is a very 'light weight' container (in more ways than one). A GUI can contain 1000s and not be burdened by doing so. Of course, that's a rare requirement, but just saying .. use panels as needed and don't worry about it.
I am trying foolish things to make the concept clear about the swings (which component i can add to which) and inheritance.
JFrame f = new JFrame();
JFrame g = new JFrame();
f.add(g); // i know that its silly.
it compiles fin because JFrame is a container and add method is defined in it. Its declaration is
Component add ( Component comp);
and if i do the funny stuff as above i get the exception saying
adding a window to a container.
What i have analysed from this is when we call a method that is defined in the above class in the inheritance tree that object is treated as an object of that above class in inheritance tree.As here when we do
f.add(g);
f is treated as container because add() is not defined in JFrame but is defined in its parent (or parent to parent more specifically) that is Container.While g is treated as Component because JFrame is a Component also.
This seems a true or false question but please explain me technically, that what i believe is right or not?
But why exception is saying
adding a window to a container.
and why not
adding a container to a component.
as g is passed to add() as a component?
My third question is that what is the need of recursive inheritance between Component and Container?
EDIT why the exception is saying so?
JFrame extends Frame extends Window extends Container extends Component
So indirectly JFrame is a Component and jframe.add(jframe2) is legal and as JFrame is child of Window message is saying that adding a window to a container. is illegal.
As it's checked in class Container as follow,
/**
* Checks that the component is not a Window instance.
*/
private void checkNotAWindow(Component comp){
if (comp instanceof Window) {
throw new IllegalArgumentException("adding a window to a container");
}
}
The hierarchy of JFrame is like this,
java.awt.Component
java.awt.Container
java.awt.Window
java.awt.Frame
javax.swing.JFrame
A JFrame is a Component, Container and a Window as well.
So, why is the exception saying adding a window to a container and not container to a container,
that's because you can add a Container to a Container. Example, JPanel to a JFrame.
You only cannot add a Window to a Container. Because Windows are for top level components and not meant to be inside another component.
And for your third question:
what is the need of recursive inheritance between Component and Container?
There's no need for that. And it's not so too. A Container is a Component. But a Component need not always be a Container. It's just multilevel inheritance you are seeing here for JFrame. Not recursive.
Can anybody tell me what is the difference between the below Code
JFrame jf=new JFrame();
JButton jb=new JButton();
jf.add(jb);
and
JFrame jf=new JFrame();
Container c=jf.getContentPane();
JButton jb=new JButton();
c.add(jb);
Even I am not Clear about the RootPane,LayeredPane,GlassPane. What is the use of RootPane?? I have never used it in my coding. I have read it from the below link
http://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html
but not too much clear because there is no practical situation where I have used the above.
Thanks for your answer!!
As of Java 5, there is no difference between you code examples. JFrame#add is now redirected to JFrame#getContentPane on your behalf.
Before Java 5, it would throw an exception, which meant you had to add your components directly to the content pane yourself.
The JRootPane is used to provide a light weight container onto which other Swing components can be added. More importantly, it provides a means by which the top level Swing containers can organise themselves.
The JRootPane is made of layers. At the bottom is the JMenuBar and content pane and above that is the glass pane.
Because of the way it's constructed, the JRootPane can actually have a number of additional layers (typically between the content pane and the glass pane), this is typically used for things like popups.
The glass pane acts as a overlay which can be used to render content over the top of everything else (as well as block mouse and keyboard events).
Take a look at How to use Root Panes.
Normally, other then the content pane and glass pane, you wouldn't typically use any of the other parts of the root pane.
You could also take a look at this for a quick example of a glass pane in use
Both are same...
Both are added in java.awt.Container object.
JFrame and Container have following hierarchy
Case 1: JFrame#add()--> Frame#add()--> Window#add()--> Container#add() // Component add to container
Case 2: JFrame#getContentPane() --> getRootPane().getContentPane(); it will return Container object(Container#add)
For some reasons (reparent a Xwindow on a Java Application) I need to add a frame into another frame... But it seems it's not possible.
Is there any mean to insert a frame (in fact a heavy weight component) into the component hierarchy of another frame?
I found three ways to fill my JFrame frame = new JFrame("...")
createContentPanel returns a JPanel and createToolBar returns a ToolBar.
frame.add(this.createToolBar(), BorderLayout.PAGE_START); //this works and puts the ToolBar above and the ContentPanel under it<br>
frame.add(this.createContentPanel(), BorderLayout.CENTER);
frame.setContentPane(this.createContentPanel()); //this lets the JToolBar hover over the ContentPanel
frame.getContentPane().add(this.createToolBar());
frame.getContentPane().add(this.createContentPanel()); //this only puts the last one into the JFrame
frame.getContentPane().add(this.createToolBar());
And now I am wondering why should i use the getContentPane()/setContentPane() method if i could just use a simple frame.add(...) to fill my frame.
You are right that it doesn't matter which you use (JFrame#add(...) vs. JFrame#getContentPane().add(...)) since they both essentially call the same code, however there will be times in the future when you'll need access to the contentPane itself, such as if you want to change its border, set its background color or determine its dimensions, and so you'll likely use getContentPane() at some point, and thus getting to know it and be familiar with it would be helpful.
//this only puts the last one into the JFrame
You need to understand how layout managers work. The default content pane is a JPanel that uses a BorderLayout. When you add a component and don't specify a constraint, then it defaults to the CENTER. However you can only has a single component in the center so the layout manager only knows about the last one added. When the layout manager is invoked it sets the size() and location() of that component. The other component has a size of 0, so it is never painted.
In Java 1.6, you can just use the add method of JFrame:
http://download.oracle.com/javase/6/docs/api/javax/swing/JFrame.html
(It will be delegated to the contentPane.)
http://download.oracle.com/javase/1.4.2/docs/api/javax/swing/JFrame.html
Which says:
The JFrame class is slightly
incompatible with Frame. Like all
other JFC/Swing top-level containers,
a JFrame contains a JRootPane as its
only child. The content pane provided
by the root pane should, as a rule,
contain all the non-menu components
displayed by the JFrame. This is
different from the AWT Frame case. For
example, to add a child to an AWT
frame you'd write:
frame.add(child);
However using JFrame you need to add the child
to the JFrame's content pane instead:
frame.getContentPane().add(child);
The same is true for setting layout
managers, removing components, listing
children, and so on. All these methods
should normally be sent to the content
pane instead of the JFrame itself. The
content pane will always be non-null.
Attempting to set it to null will
cause the JFrame to throw an
exception. The default content pane
will have a BorderLayout manager set
on it.