JavaAwtSwing笔记之 Frame和JFrame的区别

设置关闭按钮功能的区别

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

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kfepiza

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值