第一部分:JFrame中各面板间的关系,透明性与可见性问题
注:在某些地方把面板也叫做窗格,比如根面板,也叫根窗格,层面板也叫分层窗格等。注意窗格与窗体是不一样的。
在Swing中的JFrame窗体与AWT中的Frame窗体有一些不同。JFrame由他的窗体本身加上其上的JRootPane根面板,JLayeredPane层面板,containPane内容面板,glassPane玻璃面板,JMenuBar菜单栏(可选,不包括在内)四部分组成。其中根面板在JRootPane类中实现,层面板在JLayeredPane类中实现,他们都是JComponent的子类。而containPane和glassPane没有专门对应的类。
1、各种面板(或称窗格)的关系及作用:
JRootPane根面板:该面板是在JFrame窗体创建时就默认添加进来的,是所有其他面板的载体或父级,他覆盖窗体的除标题栏和边条之外的整个表面。根面板默认是不可见的。根面板负责管理其他面板(层面板,玻璃面板),如使其他面板覆盖整个JFrame窗体等。
JLayeredPane层面板:该面板是其他所有面板的父级,在JRootPane面板的上面,他再次覆盖窗体的整个表面,内容面板和JMenuBar菜单栏被添加到层面板上。当添加了菜单栏时,菜单栏被添加到JLayeredPane面板的顶部,剩下的部分被内容面板填充。层面板是分很多层的,每一层使用一个相应的数字来表示,而内容面板就位于层面板中的某一层,在后面的内容中我们可以看到层面板可以让你设计出相互重叠的内部窗体,层面板将负责管理各种内部窗体的叠放问题,对于层面板的每一层都相当于是一个容器,因此可以直接向层面板中添加组件。层面板的内容后面会作具体介绍。
containPane内容面板:由层面板的介绍可知,内容面板是层面板中的某一层。默认的内容面板是不透明的,而且是一个JPane对象。该面板在窗体中起着工作区的作用,当我们向窗体添加组件时就应该添加到这一层上,而不能像AWT那样直接添加到窗体上,若你那样做了,实际上该组件也是被添加到内容面板上的,若窗体未设置内容面板,则组件无法显示。比如要添加按钮jb则正确的方式为,Container p=jframe.getContentPane(); p.add(jr); 或jframe.getContentPane().add(jr); 其中getContentPane()是JFrame类中的方法,该方法将反回内容面板的引用,这是访问默认的内容面板的方法,因为默认的内容面板没有特定的名字,因此应使用该方法。
glassPane玻璃面板:该面板总是存在的,而且他位于最上面,默认情况下玻璃面板是不可见的,玻璃面板用于接收鼠标事件和在其他组件上绘图。
2、各面板中使用的布局管理器:
在内容面板上使用的布局管理器默认是BorderLayout。
在根面板上使用的布局管理器是一个自定义的LayoutManager(布局管理器),他的作用是布局根面板之上的其他面板。很明显如果你要向根面板中添加组件就应使用setLayout方法为其设置合适的布局管理器或自已设定组件的大小和显示位置。如果你改变了根面板自定义的LayoutManager那么你就应编写负责布局根面板之上的各种面板的程序,如果没有这样的程序,那么在根面板之上的各种面板就不能正常的布局,因此对于根面板的布局管理器一般不要随便更改。
玻璃面板的默认布局管理器是FlowLayout。
对于层面板而言,在将容器添加进层面板时,将在添加容器时指定把该容器添加进层面板的哪一层,因而某层的布局管理器由添加到该层的容器所决定,因此无需为层面板的某一层设置布局管理器,
也就是说层面板没有布局管理器。
当把某一容器(比如Panel)设为某种面板(内容面板)时,则面板的布局与添加进来的容器的布局管理器相同,比如把Panel作为内容面板,则内容面板的布局管理器就是FlowLayout。
注意:对于层面板的各层来说,只能把某种容器(比如Panel)设置为内容面板,不能把容器设置为层面板中的其他各层。
3、各面板的可见性和透明性问题
可见性使用setVisible方法来显示(在AWT时已见过不少),
透明性使用setOpaque方法来设置。setOpaque方法只有在javax.swing包中的组件才有,对于java.awt包中的组件是没有该方法的,因此要使用该方法有时需要使用强制类型转换
可见性与透明性的区别:区别在于,当面板是不可见时,则该面板中包含的组件也会不可见。若该面板是透明但可见的,则只是面板会透明(比如面板的背景色无法看到),但面板上的组件仍会显示。
根面板:默认情况下,根面板是可见且不透明的。
内容面板:默认情况下,内容面板是可见的且不透明的,因此我们创建的JFrame窗体,实际上看到的是内容面板中的内容。
玻璃面板:默认的玻璃面板是透明的且不可见的,因此要显示默认的玻璃面板应设置setVisible和setOpaque两个方法,若你把某一容器(比如Panel)设为玻璃面板,那么这时的玻璃面板仍然是不可见的,但他不是透明的,这取决于容器(比如Panel)是否是透明的。因此要把这种类型的玻璃面板显示出来只需设置setVisible方法就够了。
层面板:不管是你自已创建的层面板还是默认的层面板都是透明的且可见的,层面板中的内容面板是个特例,要使层面板可显示应设置setOpaque方法。
层面板和内容面板可见性与透明性的关系:内容面板默认在层面板的-30000层,若我们像层面板添加组件时应设置将该组件添加进层面板的哪一层,若不然就会出现一些问题,因此应使用add(Component com, Object constrainer)这个方法,在添加组件时使用add(com, new Integer(100));这样的形式,Integer对象是int装相后的结果,装相后把整数当作对象来看待,其实Integer对象就是一个整数。
内容面板和层面板及层面板之间的显示问题,因为只能把某种容器(比如Panel)设置为内容面板,不能把容器设置为层面板中的其他各层,我们也无法直接该问到层面板中的其他各层,因此层面板将只会有一种背景色(除内容面板外)且背景色使用JLayeredPane类型的对象来设置,不会存在层面板的每一层都有各自的背景色的情况,层面板透明与不透明也只能由JLayeredPane的对象来设置,不能设置层面板中各个层次的透明性。因此在层面板的各层之间他们始终是彼此透明的,无法更改,而相对与其他面板层面板(比如根面板)可以透明也可以不透明(使用JLayeredPane对象来设定)。而对于内容面板而言,由于内容面板是存在于层面板中的某一层,因此层面板中的其他层相对于内容面板也是透明的,无法更改。但是在
层面板的所有层中只有内容面板是不透明的,因此若我们既为内容面板设置了背景色也为层面板设置了背景色那么最后只会显示内容面板的背景色,除非让内容面板透明或不可见,这时才会显示出层面板的背景色。当向层面板中添加的组件在内容面板之上(大于-30000)时,这些组件将与内容面板的组件同时显示(若不重叠的话,若重叠则显示层数数值更大的组件)。若向层面板中添加的组件在内容面板之下(小于-3000层),那么内容面板将把层面板中的组件都遮挡住,因为内容面板是不透明的。
应注意的问题:
1、内容面板是层面板中的某一层。是我们的工作区间,组件都应该添加到该面板上。而不能像AWT那样直接向Frame窗体添加组件。
2、可以创建根面板的对象,但无法把该对象设置为某一个窗体的根面板,因此一般情况下JFrame窗体的根面板是唯一的。比如JRootPane jr=new JRootPane; 但不能使用JFrame中的 jframe.setRootPane(jr);方法把jr设置为该窗体的根面板,因为setRootPane方法是protected类型的,只能由继承自该类的子类的构造方法使用。
3、关于设置面板的问题:对于JFrame窗口的根面板和层面板只能把JRootPane和JLayeredPane类型的对象设为根面板和层面板,而不能把Component或Container类型的组件设为根面板或层面板。而对于玻璃面板则可以把Component类型的对象设为玻璃面板,对于内容面板可以把Container类型的对象设为内容面板。这取决于JFrame类中的set***Pane(类型 参数);方法中的"类型"是什么。对根面板其类型为JRootPane,对内容面板类型为Container
4、关于内容面板:除了默认的层面板附带有内容面板之外,你自已创建的层面板将不会拥有内容面板,这时你必须手动为层面板设置一个内容面板(比如把JPanel设为内容面板),因为层面板是不可见且透明的,因此我们现在看到的将是根面板的内容,若你为根面板设置了背景色,则将显示该背景色。比如JLayeredPane jp=new JLayeredPane(); jframe.setLayeredPane(jp); 这时若使用jframe.getContentPane().add(jb); 语句,那么按钮jb将无法显示,因为该层面板中还没有内容面板存在,在添加组件之前应把某个容器设为内容面板,比如jframe.setContentPane(jpanel);这样程序就能正常运行了。
5、关于所有面板都设为不可见或透明时的问题:若除根面板外把其他所有面板都设为不可见或透明,则若根面板设为透明,则会显示JFrame的面板,标题栏和边框。若根面板设为不可见,则我们只能看到一个框架,即只有标题栏,边框,看不见JFrame的面板。
6、关于层面板的透明问题:层面板都是透明的且不可见的,在层面板的各层之间他们始终是彼此透明的,无法更改,我们也无法直接访问到层面板中的其他各层,因此层面板将只会有一种背景色(除内容面板外)且背景色使用JLayeredPane类型的对象来设置,不会存在层面板的每一层都有各自的背景色的情况,层面板透明与不透明也只能由JLayeredPane的对象来设置,不能设置层面板中各个层次的透明性。
各层面板之间的可见性透明性及各种面板之间的关系示例:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class A {public static void main(String arg[])
{JFrame f=new JFrame(); JPanel jp1=new JPanel();
JButton jb1=new JButton("玻璃面板默认FlowLayout布局");
JButton jb2=new JButton("内容面板默认BorderLayout布局");
JButton jb3=new JButton("在内容面板之下的层面板");
JButton jb4=new JButton("根面板无默认布局");
JButton jb5=new JButton("在内容面板之上的层面板");
JButton jb6=new JButton("JFrame窗体");
//将JFrame所反回的面板都强制转换为JComponent类型,以便 调用setOpaque方法。
JComponent p1=(JComponent)f.getGlassPane();
JComponent p2=(JComponent)f.getContentPane();
JComponent p3=(JComponent)f.getLayeredPane();
JComponent p4=(JComponent)f.getRootPane();
p1.setBackground(Color.
red);
p2.setBackground(Color.
yellow);
p3.setBackground(Color.
blue);
p4.setBackground(Color.
green);
p1.add(jb1);
p2.add(jb2,BorderLayout.
SOUTH);
//为层面板p3添加两个按钮,且分别放置在内容面板之上和内容面板之下
p3.add(jb3,new Integer(-30001)); //将按钮jb3,放置在内容面板之下
p3.add(jb5,new Integer(22)); //将按钮jb5,放置在内容面板之上
jb5.setSize(200,22); jb5.setLocation(7,35);
jb3.setSize(200,22); jb3.setLocation(7,90);
//向根面板p4中添加一个按钮jb4
p4.add(jb4);
jb4.setSize(200,22); jb4.setLocation(7,60);
//f.add(jb6,BorderLayout.NORTH);//该方法实际上是把按钮jb5添加到了内容面板上,并未把jb5添加到窗体f上。
f.setLocation(222,222);
f.setSize(222,222); f.setVisible(true);
//循环显示各层面板
while(true){
//玻璃面板默认是不可见且透明的。显示玻璃面板红色背景。
try{Thread.sleep(2000); } catch (InterruptedException e) {}
p1.setVisible(true);
p1.setOpaque(true);
f.repaint(); //应使用repaint方法重缓一次,要不然会出现组件上次显示的残影
//使玻璃面板透明,但是是可见的,这样的话就会显示内容面板和层次数目在内容面板之上的层面板的内容。因为层面板自身层内之间是相互透明的,因此不会显示层面板的蓝色背景,相反内容面板是不透明的,因此会显示内容面板的背景颜色
try{Thread.sleep(2000); } catch (InterruptedException e) {}
p1.setOpaque(false);
//p1.setVisible(false); //你也可以把该行的注释删除掉,以便观察可见性与透明性的区别。
f.repaint();
//使内容面板透明,因为前面已把玻璃面板设为透明,因此会显示全部的层面板的内容,包括层面板的蓝色背景
try{Thread.sleep(2000); } catch (InterruptedException e) {}
p2.setOpaque(false);
//p2.setVisible(false);
p3.setOpaque(true);
f.repaint();
//使层面板透明,因为内容面板是层面板中的某一层,因此该设置同样会使内容面板透明,再加上之前已把玻璃面板设为透明,因此最后将会显示即不透明也是可见的根面板的内容及其绿色的背景色。
try{Thread.sleep(2000); } catch (InterruptedException e) {}
p3.setOpaque(false);
//p3.setVisible(false);
f.repaint();
//使所有面板的可见性及透明性还原。
try{Thread.sleep(2000); } catch (InterruptedException e) {}
p1.setVisible(false);
p2.setOpaque(true);
p3.setOpaque(true);
f.repaint(); }}}
程序结果按如下顺序循环显示
1、最先显示

2、两秒之后

3、再2秒之后

4、再2秒之后

5、再2秒之后
第2部分:JRootPane类
对于根面板的内容,我们在前面已介绍过,这里我们来具体看一下JRootPane类的内容,该类只有一个默认的构造方法,但要注意,若你自已创建一个JRootPane对象,那些你应该对在根面板之上的层面板,玻璃面板和菜单栏的布局负责
JRootPane类的内部类有:
JRootPane.RootLayout: 该类自定义布局管理器负责层面板,玻璃面板和菜单栏的布局。
JRootPane类的常量有:
protected Container contentPane 内容窗格(或面板)
protected JButton defaultButton 当面板成为焦点并有类似按下Enter键的特定于UI的操作发生时被激活的按钮。
protected Component glassPane 玻璃窗格,便于截取鼠标移动等操作
protected JLayeredPane layeredPane 管理菜单栏和内容窗格的分层窗格
protected JMenuBar menuBar 菜单栏
以下的常量为static int类型,都是供windowDecorationStyle属性使用的常量
COLOR_CHOOSER_DIALOG 指示JRootPane应提供适合Dialog的装饰以便显示JColorChooser
ERROR_DIALOG 指示JRootPane应提供适合Dialog的装饰以便显示一条错误消息
FILE_CHOOSER_DIALOG 指示JRootPane应提供适合Dialog的装饰以便显示JFileChooser
FRAME 指示JRootPane应提供适合Frame的装饰
INFORMATION_DIALOG 指示JRootPane应提供适合Dialog的装饰以便显示一条报告消息
NONE 指示JRootPane不应提供任何类型的Window装饰
PLAIN_DIALOG 指示JRootPane应提供适合Dialog的装饰
QUESTION_DIALOG 指示JRootPane应提供适合Dialog的装饰以便向用户显示一个问题
WARNING_DIALOG 指示JRootPane应提供适合Dialog的装饰以便显示一条警告消息
JRootPane的方法有:
protected Container createConentPane(); 由构造方法调用以创建默认的内容面板。注意该方法只能由构造方法调用。
protected Component createGlassPane(); 由构造方法调用以创建默认的玻璃面板
protected JLayeredPane createLayeredPane(); 由构造方法调用以创建默认的层面板
protected LayoutManager createRootLayout(); 由构造方法调用以创建默认的布局管理。
void setContentPane(Container co); 设置内容窗格。
void setGlassPane(Component g); 设定此根窗格的玻璃窗格
void setJMenuBar(JMenuBar m); 设置在分层窗格中使用的菜单栏
void setLayeredPane(JLayeredPane jl); 设置供根窗格使用的分层窗格
Container getContentPane(); 反回内容窗格。
Component getGlassPane(); 反回此根窗格的当前玻璃窗格
JMenuBar getJMenuBar(); 反回窗格层的菜单栏
JLayeredPane getLayeredPane(); 反回根窗格使用的分层窗格
void setDefaultButton(JButton de); 设置defaultButton属性,它确定此JRootPane的当前默认按钮。
JButton getDefaultButton(); 反回defaultButton属性的值
void setUI(RootPaneUI ui); 设置呈现此组件的L&F对象
RootPaneUI getID(); 反回呈现此组件的L&F对象。
String getUIClassID(); 反回一个指定呈现此组件的L&F类名称的字符串。
void setWindowDecorationStyle(int w); 设置JRootPane应提供的Window装饰类型。
int getWindowDecorationSytle(); 反回JRootPane提供的Window装饰类型的常量。默认不提供任何Window装饰(即外观)。其值为JRootPane类中定义的那些static int常量。
void setDoubleBuffered(boolean b); 设置此组件是否使用双缓冲技术
void updateUI(); 将UI属性重置为当前外观对应的值。
第3部分:JLayeredPane类(主要讲解组件相互重叠在一起的情况)
1、前面已介绍过,JLayperedPane层面板是分很多层的,因此,在JLayeredPane类中,为层面板的各层都赋于了一个编号,以区别正在使用的是哪一层,这个编号是一个Integer类型(把int类型装相就成为该类型)的整数,Integer实际上就是一个整数。编号数字越大的层位于编号数字更小的层的前面,也就是说当各层的子组件重叠时,高层的子组件将显示在低层中的子组件之上,即低层的子组件被高层的子组件遮挡住了。再次说明,对于层面板的每一层都相当于是一个容器,因此可以直接向层面板中添加组件。
2、为了方便JLayeredPane类定义了一些深度不同的层,这些层由JLayeredPane类中的常量所标识他们是:
DEFAULT_LAYER 默认层。该层是大多数组件位于的标准层,其值为Integer(0)
PALETTE_LAYER palette调色板层。位于默认层之上,它们对于浮动工具栏和调色板很有用,其值为Integer(100)
MODAL_LAYER 该层用于模式对话框。它们将出现在容器中所有工具栏,调色板和标准组件之上,其值为Interger(200)
POPUP_LAYER 弹出层。组合框,工具提示和与帮助文本关联的弹出式窗口将出现在组件,调色板或生生成他们的对话框之上。其值为Interger(300)
DRAG_LAYER 拖动一个组件时,将该组件重分配到拖动层可确保将其定位在容器中的其他所有组件之上。完成拖动后,可将该组件重分配到其正常层。其值为Interger(400)
FRAME_CONTENT_LAYER 内容面板层,我们经常使用的内容面板层就位于该层上。其值为Interger(-30000)
下面我们主要讲解,添加的组件相互重叠明的问题:
index索引值:a、在java中,每向容器添加一个组件都会产生一个随带的索引值,即使组件在不同的层上也不影响索引值的产生,若在同一层的多个组件相重叠时,则索引值越大的组件将被放置在越后面。索引值0表示组件在最上层,而-1表示最底层。每添加一个组件程序都会自动为其设置索引值,最先添加的组件索引值为0,第二个添加的其值为1,第三个添加的则为2,以此类推。
b、当新添加进来的组件改变了原来的索引顺序时,则所有组件的索引将重新排列,比如组件1的索引为0,组件2的为1....组件5的为4,当把组件6添加到索引位置2时,这时的索引顺序是,组件1索引为0,组件2为1,组件6为2,组件3为3,组件4为4,组件5为5。因此索引值与组件的产生顺序有关,最先产生的组件索引值小,而后面产生的组件的索引值都比紧前一个组件的大1。
c、当在比当前层更低层的面板上产生新组件时,虽然系统产生的索引值的规律是一样的,但是这时你在更低层面板上改变组件的索引值时就有一个最小值的限制,这个最小值就是当前层的组件个数。比如当前层有4个组件,因此索引值最大为3,那么更低层组件的索引值的最小值就是4。在比当前层更高层的面板上产生新组件时,不受此限制。
positon位置值:在同一层中,组件不但有一个索引值,而且组件所在的位置还有一个位置值,位置值与索引值的作用是相同的,产生的方式也是一样的,位置值与索引值的区别在于位置值只能在同一层中使用,而索引值是能跨层使用的,也就是说在不同的层中索引值是不相同的,而在不同的层中位置值有可能是相同的,比如在111层上有4个组件,那么这4个组件的索引值和位置值都分别是从0到3,这时在112层上又有3个组件,那么这两个组件的索引值可能是4到6(也有可能被你设置为0到2),而位置值则只能是0到2之间。
index索引值与position位置值的关系:索引值与位置值的功能和产生方式都是一样的,因此当你改变位置值或索引值时,索引值或位置值就会作相应的改变,当然索引值与位置值不一定是相等的,位置值取决与同一层中的组件数,而索引值则取决于所有层中的组件总数。
改变索引值的方法有add(),改变位置值的方法有setLayer()和setPosition(),moveToBack()和moveToFront()方法。
使用Container类中的void add(Component com, Object constrainer)方法。
该方法的作用是,把组件com添加到层面板中指定的层上。该方法的用法是,把Integer类型的对象指定为constrainer参数,比如layeredPane.add(component, JLayeredPane.DEFAULT_LAYER);或者layeredPane.add(component, new Integer(10))。这里要注意的是第二个参数一定要是Integer类型的,不可以使用int类型,若使用int类型,则不会出错,因为在Container类中还有一个add方法,其形式为add(Component com, int index); 表示将组件添加到指定的索引处。
使用Container类中的void add(Component com, Object constrainer, int index)方法
该方法与上面带两个参数的add方法相似,不同的是该方法将组件com添加到layerPane中指定层上的指定索引处。比如layeredPane.add(com, new Integer(10), 3); 表示将组件添加到层面板编号为10的那一层上,其位置在该层索引为3的地方。注意,这里使用的是索引值,而不是位置值,注意他们的区别。
setLayer()方法:使用该方法应注意的地方是,当使用该方法时只是把组件设置在层面板中的哪一层中出现,程序并没有把该组件添加到该层中,在使用setLayer方法后还应使用add方法把组件添加进层面板的这一层中,而且add方法应出现在setLayer方法之后。比如layerPane.setLayer(component, 3); layerPane.add(component);
该方法有2个变体,分别是:
void setLayer(Component c, int layer); 将组件c放在编号为layer的层上,并把它放置在该层的最底部。
void setLayer(Component c, int layer, int position); 将组件c放在编号为layer的层上,且把它放置在该层指定的位置值处(注意,这个方法的第3个参数是否不起作用,我在程序中试过好多次)
void setPosition(Component c, int position); 将组件c放置在当前层的position位置值(注意不是索引值)处,其中0表示放置在该层的最顶层,数值-1放置在最底层。对于其他数字,数字越大则放置在越后面。
JLayeredPane使用技巧:使用JLayeredPane类设置多层面板时应先创建一个JLayeredPane类的对象,再使用setLayeredPane方法把该对象设为窗体的层面板,这时就可以使用该对象调用JLayeredPane类中的相应方法,若使用JFrame类中的getLayeredPane方法,则不能使用JLayeredPane类中的方法,因为getLayeredPane方法反回的对象是Component对象,该对象无法调用JLayeredPane类中的方法
有了前面的知识,那么下面我们就来看看JLayeredPane类中的具体内容
JLayeredPane类中的常量有(都为static Integer类型):
DEFAULT_LAYER 默认层。该层是大多数组件位于的标准层,其值为Integer(0)
PALETTE_LAYER palette调色板层。位于默认层之上,它们对于浮动工具栏和调色板很有用,其值为Integer(100)
MODAL_LAYER 该层用于模式对话框。它们将出现在容器中所有工具栏,调色板和标准组件之上,其值为Interger(200)
POPUP_LAYER 弹出层。组合框,工具提示和与帮助文本关联的弹出式窗口将出现在组件,调色板或生生成他们的对话框之上。其值为Interger(300)
DRAG_LAYER 拖动一个组件时,将该组件重分配到拖动层可确保将其定位在容器中的其他所有组件之上。完成拖动后,可将该组件重分配到其正常层。其值为Interger(400)
FRAME_CONTENT_LAYER 内容面板层,我们经常使用的内容面板层就位于该层上。其值为Interger(-30000)
static String LAYER_PROPERTY 绑定属性。
JLayeredPane类有一个默认的构造方法
JLayeredPane类中的方法有:
Component [ ] getComponentsInLayer(int layer); 反回指定层中组件的数组
int getComponentCountInLayer(int layer); 反回指定层中组件的个数
int getIndexOf(Component c); 反回指定组件的索引值
int getLayer(Component c); 反回指定组件所在层的int值(即组件在第几层)
static int getLayer(JComponent c); 反回指定的JComponent组件在第几层。
int highestLayer(); 反回当前层面板中所拥有的子层中最顶层的层的值。
int lowestLayer(); 反回当前层面板中所拥有的子层中最底层的层的值。
boolean isOptimizedDrawingEnabled(); 判断组件是否可以重叠,若可以则反回false,否则反回true
void moveToBack(Component c); 将组件c移动到当前层中所有组件的最底层(位置-1处),只能改变位置值
void moveToFront(Component c); 将组件c移动到当前层中所有组件的最顶层(位置0处),只能改变位置值
void paint(Graphics g); 绘制此JLayeredPane
static void putLayer(JComponent c, int layer); 该方法与setLayer方法类似,只是不会产生一些副作用,比如重绘,而且只适用于JComponent组件。
void remove(int index); 从此窗格中移除索引为index的组件
void removeAll(); 从此容器中移除所有组件。
void setLayer(Component c, int layer); 将组件c放在编号为layer的层上,并把它放置在该层的最底部。
void setLayer(Component c, int layer, int position); 将组件c放在编号为layer的层上,且把它放置在该层指定的位置值处(注意,这个方法的第3个参数是否不起作用,我在程序中试过好多次)
void setPosition(Component c, int position); 将组件c放置在当前层的position位置值(注意位置值与索引值的区别)处,其中0表示放置在该层的最顶层,数值-1放置在最底层。对于其他数字,数字越大则放置在越后面。
int getPosition(Component c); 反回组件c所在层的位置值,注意位置值与索引值的区别。
JLayeredPane层面板示例:
在该示例中,我们可以看到位置值与索引值的区别,以及怎样使用多个层。具体情况请自行运行试验。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class A { public static void main(String arg[])
{JFrame f=new JFrame();
JLayeredPane p=new JLayeredPane();//要使用JLayeredPane类中的函数,应创建一个JLayeredPane的对象。
//Component p=f.getLayeredPane(); //或使用该方法则无法使用JLayeredPane类中的各种函数,因为该方法反回的结果是Component类型的,该类型是JLayeredPane的父类,父类不能使用子类中的方法,除非强制转换。
JButton jb1=new JButton("kkk1"); JButton jb2=new JButton("kkk2");
JButton jb3=new JButton("kkk3"); JButton jb4=new JButton("kkk4");
JButton jb5=new JButton("kkk5"); JButton jb6=new JButton("kkk6");
f.setLayeredPane(p); //将JLayeredPane对象p设置为窗口f的层面板。
//布置按钮jb1
p.add(jb1,new Integer(111)); //使用add方法把按钮jb1添加到层面板的111层,层面板中的每一层其实就是一个容器,因此可以直接向层面板中添加组件。
jb1.setSize(88,44); //因为层面板没有布局管理器,所以应对按钮组件的大小和位置进行设置,这里的位置使用的是默认值左上角。若不设置按钮的大小,我们最后将看不到按钮。
int ps1=p.getPosition(jb1);
System.
out.println("ps1="+ps1); //这里输出的是当前的位置值,当后面添加了新组件并设置了位置值时,该值有可能会变化。
jb1.setVisible(true);
//布置按钮jb2
p.add(jb2,new Integer(111),0); //使用add方法把按钮jb2添加到层面板的111层,并使其显示在相同层的最顶层,注意这里的0是一个索引值,而不是位置值,注意索引值与位置值position的区别
jb2.setSize(88,44);
int ps2=p.getPosition(jb2);
System.
out.println("ps2="+ps2);
jb2.setVisible(true);
//布置按钮jb3
p.setLayer(jb3,111); //使用setLayer方法将jb3按钮添加到层面板的111层,并将该组件放置在同层的最底层。
p.add(jb3);//注意该add方法,在使用setLayer方法之后一定要使用add方法,要不然组件将不能添加到层面板中
jb3.setSize(88,44);
p.setPosition(jb3, 2); //使用setPosition方法将jb3放置在索引为2的位置。
int ps3=p.getPosition(jb3);
System.
out.println("ps3="+ps3);
jb3.setVisible(true);
//布置按钮jb4
p.setLayer(jb4,111,0); //使用setLayer方法将jb4放置在层面板的111层,并使其显示在同层的最顶层上,该方法的最后一个参数无效,至于为什么,有待考证。
p.add(jb4);
jb4.setSize(88,44);
int ps4=p.getPosition(jb4);
System.
out.println("ps4="+ps4);
jb4.setVisible(true);
//布置按钮jb5
p.add(jb5,110,0); //将jb5的索引值在110层上设为0,而这实际上是不可行的,因为110层比前面使用的111层更低,这一层的索引值的最小值受到紧前层的组件个数的限制,因此对于在这一层上产生的组件的索引值的最小值是111层的组件个数4。
jb5.setSize(88,44);
jb5.setLocation(88,44); //设置jb5的位置,注意,层面板是没有布局管理器的,对于组件的位置和大小都应进行手工设置。
int ps5=p.getPosition(jb5); //反回jb5的位置值
int ind=p.getIndexOf(jb5); //反回jb5的索引值
System.
out.println("ps5="+ps5);
System.
out.println("index5="+ind);//这里可以看到索引值与位置值是不相同的,而且该层的索引值最小值为4。
jb5.setVisible(true);
//布置按钮jb6
p.add(jb6,110,1);
jb6.setSize(88,44);
jb6.setLocation(88,44);
int ps6=p.getPosition(jb6);
int ind1=p.getIndexOf(jb6);
System.
out.println("ps6="+ps6);
System.
out.println("index6="+ind1);
jb6.setVisible(true);
//改变111层组件的位置值。
p.moveToFront(jb3);
p.moveToBack(jb1);
//下面的程序将显示在111层上组件的最终位置值,请仔细观察各位置值是怎样变化的。
int a=p.getPosition(jb1); int b=p.getPosition(jb2);
int c=p.getPosition(jb3); int d=p.getPosition(jb4);
System.
out.println("a="+a+" "+"b="+b+" "+"c="+c+" "+"d="+d);
f.setSize(222,222); f.setVisible(true);}}
