Frame和JFrame的区别
- 设置关闭按钮功能的区别
- add方法的区别
- Frame默认没有Panel , JFrame默认有多个JPanel , JPanel不是Panel的子类
- JFrame继承了Frame的setMenuBar()方法, 也自己新增的setJMenuBar()方法
- 一些测试代码
设置关闭按钮功能的区别
Frame设置关闭按钮
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
或
Frame I = frame;
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
I.dispose();
}
});
或
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Window window=(Window)e.getComponent();
window.dispose();
}
});
JFrame设置关闭按钮
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
也可用和Frame相同的方式
add方法的区别
- Frame add的子件的 Parent 是 Frame
- JFrame多出getRootPane() , getGlassPane(), getLayeredPane() , getContentPane() 方法
- java5后 jframe.add() 和 jframe.getContentPane().add() 的效果相同
Frame用 add(子件)增加子件
Frame的默认layout是BorderLayout
可以用:
- .add(子部件, BorderLayout.EAST);
- .add(子部件, BorderLayout.WEST);
- .add(子部件, BorderLayout.SOUTH);
- .add(子部件, BorderLayout.NORTH);
- .add(子部件, BorderLayout.CENTER);
增加子部件
JFrame有add(子件) 和 getContentPane().add(子件)
JFrame继承自Frame
public class JFrame extends Frame implements WindowConstants,
Accessible,
RootPaneContainer,
TransferHandler.HasGetTransferHandler
JFrame直接add(子部件)方法
默认的add方法和Frame的一样, 都是继承自Container类的add方法
Jframe ▶ Frame ▶ Window ▶ Container ▶ Component ▶ Object
JFrame的默认layout也是BorderLayout
System.out.println(jframe.getLayout()); // java.awt.BorderLayout[hgap=0,vgap=0]
可以用:
- .add(子部件, BorderLayout.EAST);
- .add(子部件, BorderLayout.WEST);
- .add(子部件, BorderLayout.SOUTH);
- .add(子部件, BorderLayout.NORTH);
- .add(子部件, BorderLayout.CENTER);
增加子部件
JFrame覆盖了Container的addImpl方法, 所以 JFrame的add 和 Frame的add 不一样
据说java1.4之前 JFrame直接用add会出现不可预测的情况, 但现在可以了
add调用了addImpl
java17的源代码如下👇
protected void addImpl(Component comp, Object constraints, int index)
{
if(isRootPaneCheckingEnabled()) {
getContentPane().add(comp, constraints, index);
}
else {
super.addImpl(comp, constraints, index);
}
}
JFrame初始化时设置 setRootPaneCheckingEnabled(true); 源码👇
protected void frameInit() {
enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK);
setLocale( JComponent.getDefaultLocale() );
setRootPane(createRootPane());
setBackground(UIManager.getColor("control"));
setRootPaneCheckingEnabled(true);
if (JFrame.isDefaultLookAndFeelDecorated()) {
boolean supportsWindowDecorations =
UIManager.getLookAndFeel().getSupportsWindowDecorations();
if (supportsWindowDecorations) {
setUndecorated(true);
getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
}
}
sun.awt.SunToolkit.checkAndSetPolicy(this);
}
所以默认 jframe.add() 和 jframe.getContentPane().add()等价
JFrame的 getContentPane().add(子部件)
JFrame自带JRootPane和getRootPane() 方法 , JRootPane自带JPane
Jframe带JBootPane带JPane
getContentPane()就是调用rootPanel的getContentPane()方法, 源码如下👇
public Container getContentPane() {
return getRootPane().getContentPane();
}
getContentPane()返回RootPane的JPane, 所以JFrame自带JPane
jframe.getContentPane().getClass() 的结果是 class javax.swing.JPanel
自带JPanel的layout是 JRootPane中的匿名内部类, 继承自 BorderLayout
可以看到getContentPane()获得的JPane的Layout是一个匿名内部类
System.out.println(jframe.getContentPane().getLayout()); // javax.swing.JRootPane$1[hgap=0,vgap=0]
jframe.getContentPane().getLayout() instanceof BorderLayout 的结果是 true
在JBootPane中的源码如下👇
protected Container createContentPane() {
JComponent c = new JPanel();
c.setName(this.getName()+".contentPane");
c.setLayout(new BorderLayout() {
/* This BorderLayout subclass maps a null constraint to CENTER.
* Although the reference BorderLayout also does this, some VMs
* throw an IllegalArgumentException.
*/
public void addLayoutComponent(Component comp, Object constraints) {
if (constraints == null) {
constraints = BorderLayout.CENTER;
}
super.addLayoutComponent(comp, constraints);
}
});
return c;
}
所以JFrame 的 add() 等价 getContentPane().add() 等价 getRootPane().getContentPane().add()
JFrame 的 JRootPane
前面已述说
JFrame 默认 带 JRootPane 可通过 getRootPane()
add() 等价 getContentPane().add() 等价 getRootPane().getContentPane().add()
其实 JRootPane 也有add()方法
jframe.getRootPane().add(子件); 默认看不到, 因为被 JPanel 遮住了
用 jframe.getContentPane().setVisible(false); 将JPanel隐藏后就看到了
Frame默认没有Panel , JFrame默认有多个JPanel , JPanel不是Panel的子类
JFrame有RootPane,GlassPane,LayeredPane,ContentPane
RootPane放在JFrame上, GlassPane和LayeredPane放在RootPane上, ContentPane放在LayeredPane上面
jframe.getRootPane().getClass() 的结果是 class javax.swing.JRootPane
jframe.getRootPane().getUI().getClass() 的结果是 class javax.swing.plaf.metal.MetalRootPaneUI
jframe.getRootPane().getUIClassID() 的结果是 RootPaneUI
jframe.getRootPane().getLayout().getClass() 的结果是 class javax.swing.JRootPane$RootLayout
jframe.getRootPane().getParent()==jframe 的结果是 true
jframe.getLayeredPane().getClass() 的结果是 class javax.swing.JLayeredPane
jframe.getLayeredPane().getParent()==jframe.getRootPane() 的结果是 true
jframe.getLayeredPane().getLayout() 的结果是 null
jframe.getContentPane().getClass() 的结果是 class javax.swing.JPanel
jframe.getContentPane().getParent()==jframe.getLayeredPane() 的结果是 true
jframe.getContentPane().getLayout().getClass() 的结果是 class javax.swing.JRootPane$1
jframe.getContentPane().getLayout() instanceof java.awt.BorderLayout 的结果是 true
jframe.getGlassPane().getClass() 的结果是 class javax.swing.JPanel
jframe.getGlassPane().getParent()==jframe.getRootPane() 的结果是 true
jframe.getGlassPane().getClass() == javax.swing.JPanel.class 的结果是 true
((JPanel)jframe.getGlassPane()).getLayout().getClass() 的结果是 class java.awt.FlowLayout
getRootPane()
返回一个 javax.swing.JRootPane , 布局是自己的内部类
getGlassPane()
返回一个 javax.swing.JPanel , 布局是JPanel的默认布局 java.awt.FlowLayout
getLayeredPane()
返回一个没有布局的 javax.swing.JLayeredPane
getContentPane()
返回一个 javax.swing.JPanel , 布局被重设为 BorderLayout的子类
JFrame继承了Frame的setMenuBar()方法, 也自己新增的setJMenuBar()方法
JFrame的setMenuBar和setJMenuBar可以同时使用
一些测试代码
测试代码1
package frameJframe;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import javax.swing.*;
public class FrameJFrameCompare2205190743 {
static String separator = " 的结果是 ";
public static void pln(Object o) {System.out.println(o);}
public static void main(String[] arguments) {
Button b0 = new Button("b0");
b0.setBackground(Color.DARK_GRAY); b0.setForeground(Color.ORANGE);
final ArrayList<JButton> BtnAl = new ArrayList<>();
for(int i=1; i<=100; i++) {
JButton btn = new JButton("按钮-"+i);
btn.setBackground(new Color(0,168,255));
btn.setForeground(Color.WHITE);
btn.setSize(100, 50);
BtnAl.add(btn);
}
Frame frame = new Frame("Frame");
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Window w = (Window)e.getComponent();
pln(w==e.getOppositeWindow());
w.dispose();
System.exit(0);
}
});
frame.setBounds(100, 100, 1600, 300);
pln("frame.getParent()"+separator+frame.getParent());
pln("frame.getLayout().getClass()"+separator+frame.getLayout().getClass());
b0.setSize(100,100);
pln("frame add前 b0.getBounds()="+b0.getBounds());
frame.add(b0);
pln("frame add后 b0.getBounds()="+b0.getBounds());
frame.setVisible(true);
pln("frame.setVisible(true)后 b0.getBounds()="+b0.getBounds());
b0.setSize(100,100);
pln("再次b0.setSize(100,100);后 b0.getBounds()="+b0.getBounds());
pln("b0在Frame时的 b0.getParent()"+separator+( b0.getParent() ));
try {Thread.sleep(1000);}catch(Exception th){}
b0.setSize(100,100);
try {Thread.sleep(1000);}catch(Exception th){}
JFrame jframe = new JFrame("JFrame");
// jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Window w = (Window)e.getComponent();
pln(w==e.getOppositeWindow());
w.dispose();
System.exit(0);
}
});
jframe.setBounds(100, 500, 1600, 300);
jframe.setVisible(true);
pln("jframe.getParent()"+separator+jframe.getParent());
pln("jframe.getLayout()"+separator+jframe.getLayout());
pln("jframe.getLayout().getClass()"+separator+jframe.getLayout().getClass());
pln("jframe.getContentPane()"+separator+jframe.getContentPane());
pln("jframe.getContentPane().getClass() 的结果是 "+jframe.getContentPane().getClass());
pln("jframe.getContentPane().getLayout()"+separator+jframe.getContentPane().getLayout());
pln("jframe.getContentPane().getLayout().getClass()"+separator+jframe.getContentPane().getLayout().getClass());
pln("jframe.getContentPane().getLayout() instanceof BorderLayout"+separator+(jframe.getContentPane().getLayout() instanceof BorderLayout));
pln("jframe.getContentPane()==jframe.getRootPane() 的结果是 "+(jframe.getContentPane()==jframe.getRootPane()));
pln("jframe.getContentPane() instanceof JPanel 的结果是 "+(jframe.getContentPane() instanceof JPanel));
pln("jframe.getContentPane().getClass()==JPanel.class 的结果是 "+(jframe.getContentPane().getClass()==JPanel.class));
pln("jframe add前 b0.getBounds()="+b0.getBounds());
// JRootPane rootPane = (JRootPane) jframe.getContentPane();
jframe.add(b0,"Center");
// jframe.getContentPane().add(b0,BorderLayout.EAST);
jframe.getContentPane().add(BtnAl.get(0),BorderLayout.WEST);
jframe.getRootPane().getContentPane().add(BtnAl.get(2),BorderLayout.SOUTH);
pln("b0放到JFrame后 b0.getParent()="+b0.getParent());
pln("BtnAl.get(0).getParent()="+BtnAl.get(0).getParent());
pln("b0.getParent()==BtnAl.get(0).getParent()"+(b0.getParent()==BtnAl.get(0).getParent()));
pln("b0.getParent()==BtnAl.get(2).getParent()"+(b0.getParent()==BtnAl.get(2).getParent()));
JRootPane jrootPane = jframe.getRootPane();
final JPanel JFrameJRootPaneJPane = (JPanel) jframe.getContentPane();
final JPanel JRootPaneJPane = (JPanel) jrootPane.getContentPane();
pln("JFrameJRootPaneJPane==JRootPaneJPane"+separator+ (JFrameJRootPaneJPane==JRootPaneJPane) );
// JFrameJRootPaneJPane.setVisible(false);
jframe.getContentPane().setVisible(false);
// jframe.add(BtnAl.get(0));
jrootPane.add(BtnAl.get(1));
pln("BtnAl.get(1).getParent()="+BtnAl.get(1).getParent());
jrootPane.invalidate();
jframe.setVisible(true);
// jframe.dispose();
// jframe.setVisible(true);
}
}
结果
frame.getParent() 的结果是 null
frame.getLayout().getClass() 的结果是 class java.awt.BorderLayout
frame add前 b0.getBounds()=java.awt.Rectangle[x=0,y=0,width=100,height=100]
frame add后 b0.getBounds()=java.awt.Rectangle[x=0,y=0,width=100,height=100]
frame.setVisible(true)后 b0.getBounds()=java.awt.Rectangle[x=8,y=31,width=1584,height=261]
再次b0.setSize(100,100);后 b0.getBounds()=java.awt.Rectangle[x=8,y=31,width=100,height=100]
b0在Frame时的 b0.getParent() 的结果是 java.awt.Frame[frame0,100,100,1600x300,invalid,layout=java.awt.BorderLayout,title=Frame,resizable,normal]
jframe.getParent() 的结果是 null
jframe.getLayout() 的结果是 java.awt.BorderLayout[hgap=0,vgap=0]
jframe.getLayout().getClass() 的结果是 class java.awt.BorderLayout
jframe.getContentPane() 的结果是 javax.swing.JPanel[null.contentPane,0,0,1584x261,layout=javax.swing.JRootPane$1,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
jframe.getContentPane().getClass() 的结果是 class javax.swing.JPanel
jframe.getContentPane().getLayout() 的结果是 javax.swing.JRootPane$1[hgap=0,vgap=0]
jframe.getContentPane().getLayout().getClass() 的结果是 class javax.swing.JRootPane$1
jframe.getContentPane().getLayout() instanceof BorderLayout 的结果是 true
jframe.getContentPane()==jframe.getRootPane() 的结果是 false
jframe.getContentPane() instanceof JPanel 的结果是 true
jframe.getContentPane().getClass()==JPanel.class 的结果是 true
jframe add前 b0.getBounds()=java.awt.Rectangle[x=8,y=31,width=100,height=100]
b0放到JFrame后 b0.getParent()=javax.swing.JPanel[null.contentPane,0,0,1584x261,invalid,layout=javax.swing.JRootPane$1,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
BtnAl.get(0).getParent()=javax.swing.JPanel[null.contentPane,0,0,1584x261,invalid,layout=javax.swing.JRootPane$1,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
b0.getParent()==BtnAl.get(0).getParent()true
b0.getParent()==BtnAl.get(2).getParent()true
JFrameJRootPaneJPane==JRootPaneJPane 的结果是 true
BtnAl.get(1).getParent()=javax.swing.JRootPane[,8,31,1584x261,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777675,maximumSize=,minimumSize=,preferredSize=]
测试代码2
package jframe;
import java.awt.*;
import javax.swing.*;
public class JFrame自带的Panel_2205210825 {
static void pln() {System.out.println();}
static void pln(Object o) {System.out.println(o);}
static void pln(Object o1, Object o2) {pln(o1+" 的结果是 "+o2);}
static JFrame jframe = new JFrame("JFrame010");
static JMenuBar jMenuBar = new JMenuBar();
static MenuBar menuBar = new MenuBar();
public static void main(String[] args) {
pln("jframe.getRootPane().getClass()", jframe.getRootPane().getClass());
pln("jframe.getRootPane().getUI().getClass()", jframe.getRootPane().getUI().getClass());
pln("jframe.getRootPane().getUIClassID()", jframe.getRootPane().getUIClassID());
pln("jframe.getRootPane().getLayout().getClass()", jframe.getRootPane().getLayout().getClass());
pln("jframe.getRootPane().getParent()==jframe", jframe.getRootPane().getParent()==jframe);
pln("");
pln("jframe.getLayeredPane().getClass()", jframe.getLayeredPane().getClass());
pln("jframe.getLayeredPane().getParent()==jframe.getRootPane()", jframe.getLayeredPane().getParent()==jframe.getRootPane());
pln("jframe.getLayeredPane().getLayout()", jframe.getLayeredPane().getLayout());
pln("");
pln("jframe.getContentPane().getClass()", jframe.getContentPane().getClass());
pln("jframe.getContentPane().getParent()==jframe.getLayeredPane()", jframe.getContentPane().getParent()==jframe.getLayeredPane());
pln("jframe.getContentPane().getLayout().getClass()", jframe.getContentPane().getLayout().getClass());
pln("jframe.getContentPane().getLayout() instanceof java.awt.BorderLayout", jframe.getContentPane().getLayout() instanceof java.awt.BorderLayout);
pln("");
pln("jframe.getGlassPane().getClass()", jframe.getGlassPane().getClass());
pln("jframe.getGlassPane().getParent()==jframe.getRootPane()", jframe.getGlassPane().getParent()==jframe.getRootPane());
pln("jframe.getGlassPane().getClass() == javax.swing.JPanel.class", jframe.getGlassPane().getClass() == javax.swing.JPanel.class);
pln("((JPanel)jframe.getGlassPane()).getLayout().getClass()", ((JPanel)jframe.getGlassPane()).getLayout().getClass());
pln("");
pln("默认jframe.getMenuBar()", jframe.getMenuBar());
pln("默认jframe.getJMenuBar()", jframe.getJMenuBar());
pln();
jframe.setMenuBar(menuBar);
pln("jframe.setMenuBar(menuBar);"+" 之后");
pln("menuBar.getParent()", menuBar.getParent());
pln("menuBar.getParent()==jframe", menuBar.getParent()==jframe);
pln();
jframe.setJMenuBar(jMenuBar);
pln("jframe.setJMenuBar(jMenuBar);"+" 之后");
pln("jMenuBar.getParent()", jMenuBar.getParent());
pln("jMenuBar.getParent()==jframe.getLayeredPane()", jMenuBar.getParent()==jframe.getLayeredPane());
}
}
jframe.getRootPane().getClass() 的结果是 class javax.swing.JRootPane
jframe.getRootPane().getUI().getClass() 的结果是 class javax.swing.plaf.metal.MetalRootPaneUI
jframe.getRootPane().getUIClassID() 的结果是 RootPaneUI
jframe.getRootPane().getLayout().getClass() 的结果是 class javax.swing.JRootPane$RootLayout
jframe.getRootPane().getParent()==jframe 的结果是 true
jframe.getLayeredPane().getClass() 的结果是 class javax.swing.JLayeredPane
jframe.getLayeredPane().getParent()==jframe.getRootPane() 的结果是 true
jframe.getLayeredPane().getLayout() 的结果是 null
jframe.getContentPane().getClass() 的结果是 class javax.swing.JPanel
jframe.getContentPane().getParent()==jframe.getLayeredPane() 的结果是 true
jframe.getContentPane().getLayout().getClass() 的结果是 class javax.swing.JRootPane$1
jframe.getContentPane().getLayout() instanceof java.awt.BorderLayout 的结果是 true
jframe.getGlassPane().getClass() 的结果是 class javax.swing.JPanel
jframe.getGlassPane().getParent()==jframe.getRootPane() 的结果是 true
jframe.getGlassPane().getClass() == javax.swing.JPanel.class 的结果是 true
((JPanel)jframe.getGlassPane()).getLayout().getClass() 的结果是 class java.awt.FlowLayout
默认jframe.getMenuBar() 的结果是 null
默认jframe.getJMenuBar() 的结果是 null
jframe.setMenuBar(menuBar); 之后
menuBar.getParent() 的结果是 javax.swing.JFrame[frame0,0,0,0x0,invalid,hidden,layout=java.awt.BorderLayout,title=JFrame010,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
menuBar.getParent()==jframe 的结果是 true
jframe.setJMenuBar(jMenuBar); 之后
jMenuBar.getParent() 的结果是 javax.swing.JLayeredPane[null.layeredPane,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,optimizedDrawingPossible=true]
jMenuBar.getParent()==jframe.getLayeredPane() 的结果是 true