zoukankan      html  css  js  c++  java
  • JFrame 的层次结构 及 背景设置说明

    感谢原文:https://blog.csdn.net/qq_32006373/article/details/49659129

    一、JFrame 的层次结构

    我们通过两个图来说明一下 JFrame 的层次结构:

    从视觉效果来看(从 View 层来看),一个 JFrame 的结构是这样的:
    在这里插入图片描述在这里插入图片描述
    可以看出,
    Frame 的最底层是 RootPane,
    然后是 LayeredPane
    再上面就是 ContentPane
    最顶层是 GlassPane

    最顶层的 GlassPane 默认是透明的,
    关于 GlassPane 这个层次,其实有很多可以利用的技巧,以后我再慢慢告诉大家,
    今天说我们的重点:ContentPane
    可以看出,这个 ContentPane 就是默认盛放控件的那个层次,
    那 ContentPane 在默认的情况下又是什么呢?

    我们来看两个方法:

    JFrame 中的 getContentPane:
    
    public Container getContentPane() {
    return getRootPane().getContentPane();
    }
    
    JRootPane 中的 createContentPane:
    
    protected Container createContentPane() {
    JComponent c = new JPanel();
    ……
    ……
    return c;
    }
    

    可以明显的看出,默认的 ContentPane 就是一个 JPanel;

    现在我们再来看另一张图,从模型的角度来看 JFrame 的层次:
    在这里插入图片描述
    可以看出,其实 ContentPane 是添加在 LayeredPane 上的一个控件。
    而 LayeredPane 和 GlassPane 是直接添加在 RootPane 上的,
    RootPane 直接添加在 JFrame 上。

    其实你只要记住:
    1、你现在不再需要去 getContentPane(),
    2、ContentPane 默认是一个 JPanel ,
    这两个结论就可以了……
    在这里插入图片描述

    二、java中如何对JFrame设置背景颜色及背景图片

    setVisible()说明:当设置为flase时,组件本身及增加在该组件上的组件都不可见;

    setOpaque()说明: 当设置为flase时,只针对设置了透明的组件,其他组件不受影响;

    Java窗口是指JFrame或者Frame
    其次,窗口背景颜色是指直接调用JFrame或者Frame的setBackground(Color color)方法设置后显示出来的颜色。其实,J在你直接调用这个方法后,你的确设置了背景颜色,而你看到的却不是直接的JFrame或者Frame,而是JFrame.getContentPane().而JFrame上的contentPane默认是Color.WHITE的,所以,无论你对JFrame或者Frame怎么设置背景颜色,你看到的都只是contentPane.

    最后,讲解决办法:

    办法A:在完成初始化,调用getContentPane()方法得到一个contentPane容器,然后将其设置为不可见,即setVisible(false)。这样,你就可以看到JFrame的庐山真面貌啦!

    核心代码this.getContentPane().setVisible(false);//得到contentPane容器,设置为不可见

    方法B:将contentPane的颜色设置为你想要的颜色,而不是对JFrame本身设置;

    核心代码:this.getContentPane().setBackground(Color.red);//设置contentPane为红色

    将核心代码替换方法A核心代码即可实现

    方法C:为JFrame添加一个Panel或者JLabel等其他组件,设置其颜色为你想要的颜色,然后将其覆盖JFrame窗口即可

    JFrame默认是BorderLayout
    JPanel默认是FlowLayout

    1.JFrame设置背景色,注意体会注释的

    package com.tools; import java.awt.Color;import javax.swing.JFrame;
    public class Test extends JFrame
    {
    public static void main(String[] args)
    {
       new Test();
    }
    
    
    public Test()
    {
       this.setSize(400,300);
       this.setLocation(400,300);
       this.setBackground(Color.blue);
       this.getContentPane().setBackground(Color.red);
       this.getContentPane().setVisible(false);//如果改为true那么就变成了红色。
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       this.setVisible(true);
    }
    }
    

    2.给JFrame设置背景图片。

      方法1:通过在JFrame中添加一个JPanel,背景图片放在JPanel上来实现。代码如下:
    
    import java.awt.*; 
    import javax.swing.*;
    public class Test extends JFrame
    {
    //创建一个容器
    Container ct;
    //创建背景面板。
    BackgroundPanel bgp;
    
    //创建一个按钮,用来证明我们的确是创建了背景图片,而不是一张图片。
    JButton jb;
    public static void main(String[] args)
    {
       new Test();
    }
    public Test()
    {
       //不采用任何布局方式。
    ct=this.getContentPane();
       this.setLayout(null);
    
       //在这里随便找一张400*300的照片既可以看到测试结果。
    bgp=new BackgroundPanel((new ImageIcon("images\background.jpg")).getImage());
       bgp.setBounds(0,0,400,300);
       ct.add(bgp);
    
       //创建按钮
    jb=new JButton("测试按钮");
    jb.setBounds(60,30,160,30);
       ct.add(jb);
    
       this.setSize(400,300);
       this.setLocation(400,300);
       this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       this.setVisible(true);
    }
    }
    class BackgroundPanel extends JPanel
    {
    Image im;
    public BackgroundPanel(Image im)
    {
       this.im=im;
       this.setOpaque(true);
    }
    //Draw the back ground.
    public void paintComponent(Graphics g)
    {
       super.paintComponents(g);
       g.drawImage(im,0,0,this.getWidth(),this.getHeight(),this);
    
    }
    }
    

    方法2:我们用JLayeredPane,JLayeredPane 为 JFC/Swing 容器添加了深度,允许组件在需要时互相重叠。Integer 对象指定容器中每个组件的深度,其中编号较高的组件位于其他组件之上
    在这里插入图片描述

    /**
    * 给JFrame 添加一个背景图案。
    */
    package com.swingpractise; 
    import javax.swing.*;
     public class JFrameBackground4 extends JFrame
    {
    //创建一个JLayeredPane用于分层的。
    JLayeredPane layeredPane;
    //创建一个Panel和一个Label用于存放图片,作为背景。
    JPanel jp;
    JLabel jl;
    ImageIcon image;
    
    //创建一个按钮用于测试的。
    JButton jb;
    public static void main(String[] args)
    {
       new JFrameBackground4();
    }
    
    public JFrameBackground4()
    {
       layeredPane=new JLayeredPane();
       image=new ImageIcon("images\background.jpg");//随便找一张图就可以看到效果。  
    //创建背景的那些东西
    jp=new JPanel();
       jp.setBounds(0,0,image.getIconWidth(),image.getIconHeight());   
       jl=new JLabel(image);
    //   jl.setBounds(0,0,image.getIconWidth(),image.getIconHeight());
       jp.add(jl);
    
       //创建一个测试按钮
    jb=new JButton("测试按钮");
    jb.setBounds(100,100,100,100);
    
       //将jp放到最底层。
    layeredPane.add(jp,JLayeredPane.DEFAULT_LAYER);
       //将jb放到高一层的地方
    layeredPane.add(jb,JLayeredPane.MODAL_LAYER);
    
       this.setLayeredPane(layeredPane);
       this.setSize(image.getIconWidth(),image.getIconHeight());
       this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       this.setLocation(image.getIconWidth(),image.getIconHeight());
       this.setVisible(true); 
    }
    }
    

    在这里插入图片描述在这里插入图片描述
    第二个程序和三个程序的窗体

    Java中有关Frame背景的设置总结

    我们在进行图形用户界面编程时,为了做出一个漂亮、个性化的界面,那么界的背景就必须考虑了。
    要想灵活使用背景,就一定要对frame的基本有一些了解,因为在java编程中没有直接设置背景的有关方法,
    了解一些基本知识后我们就可以随意设置背景了。
    首先还是要了解框架JFrame中的层次结构。
    JFrame中的层次分布及相对关系是:
    最底层是:JRootPane;
    第二层是:JlayerPane,这层上面包含一层ContentPane(默认不透明),也正是我们常说的内容面板。
    所以一般我们拖放的控件就是在ContentPane层上。;
    最上层就是:GlassPane(默认是透明的);
    有了这些常识后我们就可以随意设计背景了。
    在这里笔者提供两种方法为一个
    frame设置一张背景图片。
    方法一:
    原理:
    我们把图片放置在第二层:JlayerPane容器上,然后让最上层的:
    ContentPane透明,这样就实现了背景的设置。(当然把图片放置最低层,让上面两层透明也是可以的)
    具体步骤:
    // 加载背景图片
    ImageIcon bg = new ImageIcon(“background.jpg”);
    // 把背景图片显示在一个标签里
    JLabel label = new JLabel(bg);
    //把标签的大小位置设置为图片刚好填充整个面
    label.setBounds(0,0,bg.getIconWidth(),bg.getIconHeight());
    //添加图片到frame的第二层
    frame.getLayeredPane().add(label,newInteger(Integer.MIN_VALUE));
    //获取frame的最上层面板为了设置其背景颜色(JPanel有设置透明的方法)
    JPanel jp=(JPanel)frame.getContentPane();
    jp.setOpaque(false); //设置透明
    //测试用的JPanel
    JPanel panel=new JPanel();
    panel.setOpaque(false); //也要让他透明
    panel.setLayout(null);
    //为了使用按钮的定位
    JButton button=new JButton(“OK”);
    button.setSize(100, 20);
    button.setLocation(100, 50);
    panel.add(button);
    frame.add(panel);
    效果如图:
    方法二:
    原理:
    我们直接在最上层容器内重写paintComponent(Graphics g)方法在容器中画一张图片。(这种方法很直观,原理很简单)
    具体步骤:
    只需要在构造JPanel时重写paintComponent(Graphics g)就ok了。
    class PanelTest extends JPanel{
    ImageIcon background = new ImageIcon(“background.jpg”);
    //加载图片
    Image im=Toolkit.getDefaultToolkit().getImage(“background.jpg”);
    int h,w;
    public void paintComponent(Graphics g) {
    g.drawImage(im, 0, 0, null);
    }
    }

    总结:
    只要了解了基本原理我们就可以更随意一点设计我们的风格了,我在这了抛砖引玉,希望对初学者有所帮助。


    感谢原文:https://blog.csdn.net/xietansheng/article/details/74366560

    补充:

    Java Swing 图形界面开发(目录)

    1. 概述
      官方JavaDocsApi: javax.swing.JLayeredPane

    JLayeredPane,层级面板。

    JLayeredPane为容器添加了深度,允许组件在需要时互相重叠。

    JLayeredPane将深度范围按 层 划分,在同一层内又对组件按位置进一步划分,将组件放入容器时需要指定组件所在的层,以及组件在该层内的 位置(position/index)。

    层的编号越大越显示在前面;同层内位置编号越大越靠近底部(位置编号取值范围: [-1, n - 1],n 表示层内组件数量,其中 -1 表示最底,0 表示最顶)。

    通过 setLayer(Component c, int layer) 可设置组件所在的层数。

    同一层内的组件,可通过调用 moveToFront(Component)、moveToBack(Component) 和 setPosition(int) 调整层内的位置。

    PS: 添加到 JLayeredPane 内的组件需要明确指定组在位置和宽高,否则不显示(类似绝对布局)。

    JLayeredPane 构造方法:

    // 创建一个层及面部
    JLayeredPane()
    
    

    JLayeredPane 常用方法:

    /**
     * 添加组件到指定的层(默认放到层内最底部),参数说明:
     *     comp: 待添加的组件
     *     layer: 所在的层, 层数是int类型, 由于该方法与另一个 add(Component, int) 方法类似, 直接使用会有冲突, 所以使
     *            用该方法传递 layer 参数时, 必须使用 Integer 类型来明确调用的是下面 add(Component, Object) 方法。
     */
    void add(Component comp, Object layer)
    
    // 添加组件到指定的层和层内的位置
    void add(Component comp, Object layer, int position)
    
    // 设置组件所在层(默认放到层内最底部)
    void setLayer(Component c, int layer)
    
    // 设置组件所在层,以及在层内的位置
    void setLayer(Component c, int layer, int position)
    
    // 移动组件到其所在层的最顶部位置
    void moveToFront(Component c)
    
    // 移动组件到其所在层的最底部位置
    void moveToBack(Component c)
    
    // 设置组件在其所在层的位置,其中 position 取值范围为: [-1, n - 1],n 表示层内组件数量,其中 -1 表示最底,0 表示最顶
    void setPosition(Component c, int position)
    
    

    2. 代码实例

    package com.xiets.swing;
    
    import javax.swing.*;
    import java.awt.*;
    
    public class Main {
    
        public static void main(String[] args) {
            JFrame jf = new JFrame("测试窗口");
            jf.setSize(300, 300);
            jf.setLocationRelativeTo(null);
            jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    
            JLayeredPane layeredPane = new JLayeredPane();
    
            // 层数: 100
            JPanel panel_100_1 = createPanel(Color.RED, "L=100, P=1", 30, 30, 100, 100);
            layeredPane.add(panel_100_1, new Integer(100));
    
            // 层数: 200, 层内位置: 0(层内顶部)
            JPanel panel_200_0 = createPanel(Color.GREEN, "L=200, P=0", 70, 70, 100, 100);
            layeredPane.add(panel_200_0, new Integer(200), 0);
    
            // 层数: 200, 层内位置: 1
            JPanel panel_200_1 = createPanel(Color.CYAN, "L=200, P=1", 110, 110, 100, 100);
            layeredPane.add(panel_200_1, new Integer(200), 1);
    
            // 层数: 300
            JPanel panel_300 = createPanel(Color.YELLOW, "L=300", 150, 150, 100, 100);
            layeredPane.add(panel_300, new Integer(300));
    
            jf.setContentPane(layeredPane);
            jf.setVisible(true);
        }
    
        /**
         * 创建一个面板容器(容器内包含一个水平方向居中, 垂直方向顶部对其的标签)
         *
         * @param bg 容器背景
         * @param text 容器内标签显示的文本
         * @param x 容器的横轴坐标
         * @param y 容器的纵坐标
         * @param width 容器的宽度
         * @param height 容器的高度
         * @return
         */
        private static JPanel createPanel(Color bg, String text, int x, int y, int width, int height) {
            // 创建一个 JPanel, 使用 1 行 1 列的网格布局
            JPanel panel = new JPanel(new GridLayout(1, 1));
    
            // 设置容器的位置和宽高
            panel.setBounds(x, y, width, height);
    
            // 设置 panel 的背景
            panel.setOpaque(true);
            panel.setBackground(bg);
    
            // 创建标签并设置相应属性
            JLabel label = new JLabel(text);
            label.setHorizontalAlignment(SwingConstants.CENTER);
            label.setVerticalAlignment(SwingConstants.TOP);
    
            // 添加标签到容器
            panel.add(label);
    
            return panel;
        }
    
    }
    
    

    结果:

    在这里插入图片描述
    本人代码练习:

    package test;
    
    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.GridLayout;
    
    import javax.swing.ImageIcon;
    import javax.swing.JFrame;
    import javax.swing.*;
    import javax.swing.JPanel;
    
    public class TestAgain {
    
    	public static void main(String[] args) {
    		 JFrame f1=new JFrame("Calculator");
    		 f1.setBounds(0,0,400,200);
    		 //f1.setBackground(Color.RED);
    		 
    		 JPanel p1,p2,p3;
    		 p1=new JPanel(); 
    		 p2=new JPanel();
    		 p3=new JPanel();
    		 p1.setBounds(10,10,50,50);
    		 p2.setBounds(20,20,50,50);
    		 p3.setBounds(30,30,50,50);
    		 p1.setBackground(Color.RED);
    		 p2.setBackground(Color.YELLOW);
    		 p3.setBackground(Color.BLUE);
    		 
    		 JLayeredPane lay1=new JLayeredPane();
    //		 lay1.add(p1,JLayeredPane.DEFAULT_LAYER);
    //		 lay1.add(p2,JLayeredPane.PALETTE_LAYER);
    //		 lay1.add(p3,JLayeredPane.MODAL_LAYER);
    		 lay1.add(p1,new Integer(1));
    		 lay1.add(p2,new Integer(1));
    		 lay1.add(p3,new Integer(1));
    		 //不同层,Integer数值小,层越靠近底部//同层Integer值越小,越靠近顶部
    		 lay1.setPosition(p3,new Integer(0));
    		 
    		 
    		 f1.setLayeredPane(lay1);
    		 ((JPanel)(f1.getContentPane())).setOpaque(false);
    		  f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		  f1.setVisible(true);
    
    	}
    
    }
    
    

    再补充:

    感谢原文:https://blog.csdn.net/kewbblog/article/details/8625917

    Swing的容器结构与JLayeredPane的使用

    类层次结构图:
    java.lang.Object
    –java.awt.Compontent
    –java.awt.Container
    –javax.swing.JComponent
    –javax.swing.JLayeredPane
    我们可把Swing容器的结构看似如下图所示:

         |Grass Pane
         |
    

    Root Pane|
    | |Content Pane
    |Layered Pane|
    |Menu Bar
    其中,Root Pane可以看成是虚拟的容器,包含着Grass Pane、Layered Pane、Content Pane与Menu Bar.Swing的容器包括JApplet ,JFrame,JDialog,JWindow与JInternalFrame都是构造在此结构上,JApplet、JFrame、JDialog、JWindow都是heavyweight容器,只 有JInternalFrame是lightweight容器。当我们要加入某个组件到Swing的容器中时,并不是直接加入到Root Pane,而是加入到 RootPane下面的某一成员(Layered Pane或Content Pane)
    Content Pane与Menu Bar只是Layered Pane的其中一层,我们称此层为Frame-Content Layer.若你想知道Frame-Content Layer 在Layered Pane的层次是什么?你可以由JLayeredPane类中的Frame_Content_layer类常数取得。


    补充:

    	持续组件居中方法:监听
    

    在这里插入图片描述

  • 相关阅读:
    [POJ 2096]Collecting Bugs
    [SPOJ 375]Query on a tree
    [BZOJ 4423][AMPPZ2013]Bytehattan
    [BZOJ 2038][2009国家集训队]小Z的袜子(hose)
    [SDOI 2017]数字表格
    [NOI 2010]能量采集
    [HNOI 2014]世界树
    [HNOI 2016]序列
    [HNOI 2016]大数
    [HEOI 2014]大工程
  • 原文地址:https://www.cnblogs.com/tfxz/p/12621736.html
Copyright © 2011-2022 走看看