
swing布局
-
2023年3月5日发(作者:日语教程)Java基础——GUI——Swing介绍、常⽤组件、布局管理器、
事件处理、监听器的多种实现⽅式
⽬录
中的GUI
GUI(GraphicalUserInterface):图形⽤户界⾯
Java的GUI程序设计技术主要包括AWT、Swing和SWT(使⽤SWT需要从⽹上下载安装额外的Java包)
AWT的类是使⽤原始的GUI对象来运⾏,在不同的操作系统上,底层对于界⾯的显⽰⽀持不同,导致AWT的程序在不同操作系统上不兼容
Swing包中提供的类加强了对各种操作系统的兼容性,在Java中,对于不同的操作系统,这些类可以更加充分地发挥作⽤,Swing类⽀持许
多AWT中相似的类所不能⽀持的特性,但Swing并没有完全替代AWT
(1)AWT
包是Java内置的包,属于Java基本类库(JFO)的⼀部分
.*
(2)Swing
轻量级组件
可插⼊外观组件(并且外观不随操作系统⽽发⽣变化)
Swing是在AWT基础上发展⽽来的轻量级组件(AWT时),与AWT相⽐不但改进了⽤户界⾯,⽽且所需的系统资源更少
Swing是纯Java组件,完全由Java编写,使所有的应⽤程序在不同的平台上运⾏时具有本机外观和相同的⾏为
Swing不仅包括了AWT所具有的全部组件,⽽且可以使⽤树形组件(JTree)、表格(JTable)、选项卡(JTabbedPane)等⾼级图
形组件
事实上,AWT和Swing技术极为相似,GUI组件的类名通常只是⽐AWT组件的类名多了⼀个字J
中常⽤容器和组件
(1)常⽤容器
(2)常⽤组件
3.布局管理器
想在窗体上添加组件,我们就应该清楚是要在窗体的哪⼀部分添加组件,⽽窗体本⾝的区域就是容器(Container类型),我们可以通过获
取⽅法获得Container对象,然后可以创建组件,通过add⽅法将组件添加到容器中,⽽这个组件添加进去在容器中怎
么放置就是“布局”
布局管理器:能够决定组件或其他窗体中的排列规则的对象
布局管理器是⽤来设置容器的布局⽅式的
(1)绝对布局(空布局)
使⽤绝对布局的窗⼝通常都是固定⼤⼩的,组件的位置和形状不会随着窗体的改变⽽发⽣变化。
ner;
n;
;
publicclassMyJFrameextendsJFrame{
//创建按钮的引⽤
privateJButtonbutton1;
privateJButtonbutton2;
//在构造界⾯的时候就进⾏初始化界⾯
publicMyJFrame(){
init();
}
//初始化界⾯
privatevoidinit()
{
//设置窗体
e(600,400);//设置窗体⼤⼩
ationRelativeTo(null);//设置窗体居中显⽰
le("Java⽹格布局管理器⽰例");//设置窗体标题
aultCloseOperation(EXIT_ON_CLOSE);//设置点击窗体x号时退出程序
//为按钮引⽤创建按钮对象
button1=newJButton("按钮1");
button2=newJButton("按钮2");
//获取Frame界⾯容器
Containercontainer=tentPane();
//设置容器布局为绝对布局,即组件的摆放不受任何限制
out(null);
//为按钮设置位置和⼤⼩
ation(0,0);
e(200,100);
nds(100,150,200,100);
//向Frame的容器中加⼊按钮组件
(button1);
(button2);
}
publicstaticvoidmain(String[]args){
MyJFrameframe=newMyJFrame();
ible(true);
}
}
空布局优缺点:
优点:组件摆放灵活
缺点:代码量⼤,⾃适应能⼒差
(2)流布局管理器FlowLayout
组件的排列⽅向:
使⽤此⽅法来设置排列⽅向,通过
参数设置⽅向,此处为从右向左排列
组件的对齐⽅式:
默认居中对齐:
左对齐:
跟队头对齐(即第⼀个进⼊窗体的组件对齐):
组件是否换⾏:
组件会⾃动换⾏
设置组件之间的距离
第⼀个参数:对齐⽅式
第⼆个参数:横向间隔距离
第三个参数:纵向间隔距离
entOrientation;
ner;
yout;
n;
;
publicclassMyJFrameextendsJFrame{
//创建按钮的引⽤
privateJButtonbutton1;
privateJButtonbutton2;
//在构造界⾯的时候就进⾏初始化界⾯
publicMyJFrame(){
init();
}
//初始化界⾯
privatevoidinit()
{
//设置窗体
e(600,400);//设置窗体⼤⼩
ationRelativeTo(null);//设置窗体居中显⽰
le("Java窗体⽰例");//设置窗体标题
aultCloseOperation(EXIT_ON_CLOSE);//设置点击窗体x号时退出程序
//为按钮引⽤创建按钮对象
button1=newJButton("按钮1");
button2=newJButton("按钮2");
//获取Frame界⾯容器
Containercontainer=tentPane();
//为窗体容器设置布局
out(newFlowLayout(G,100,30));
ponentOrientation(_TO_LEFT);
//向Frame的容器中加⼊按钮组件
(button1);
(button2);
}
publicstaticvoidmain(String[]args){
MyJFrameframe=newMyJFrame();
ible(true);
}
}
(3)边框布局管理器BorderLayout
布局⽅式:把窗体划分成东、南、西、北、中五个区域
Layout;
entOrientation;
ner;
yout;
n;
;
publicclassMyJFrameextendsJFrame{
//创建按钮的引⽤
privateJButtonbutton1;
privateJButtonbutton2;
privateJButtonbutton3;
privateJButtonbutton4;
privateJButtonbutton5;
//在构造界⾯的时候就进⾏初始化界⾯
publicMyJFrame(){
init();
}
//初始化界⾯
privatevoidinit()
{
//设置窗体
e(600,400);//设置窗体⼤⼩
ationRelativeTo(null);//设置窗体居中显⽰
le("Java边框布局管理器⽰例");//设置窗体标题
aultCloseOperation(EXIT_ON_CLOSE);//设置点击窗体x号时退出程序
//为按钮引⽤创建按钮对象
button1=newJButton("按钮1");
button2=newJButton("按钮2");
button3=newJButton("按钮3");
button4=newJButton("按钮4");
button5=newJButton("按钮5");
//获取Frame界⾯容器
Containercontainer=tentPane();
out(newBorderLayout());
//向Frame的容器中加⼊按钮组件
(button1,);
(button2,);
(button3,);
(button4,);
(button5,);
}
publicstaticvoidmain(String[]args){
MyJFrameframe=newMyJFrame();
ible(true);
}
}
通过修改BorderLayout的构造⽅法的参数,可以为组件之间设置间距
5代表横向间距为5个像素
10代表纵向间距为10个像素
注意:
1.中间区域空缺的情况下,四周区域不会占据中间的区域
2.四边的组件⼀旦有空缺,中间的组件会占据四边的空间
3.五个区域中,每个区域只能放置⼀个组件
(3)⽹格布局管理器GridLayout
布局⽅式:把整个窗体看成是⼀个N⾏M列的⼆维⽹格阵列,窗体上的每个组件都占据⼀个⽹格,⽹格的⼤⼩均匀
Layout;
entOrientation;
ner;
yout;
yout;
n;
;
publicclassMyJFrameextendsJFrame{
//创建按钮的引⽤
privateJButtonbutton1;
privateJButtonbutton2;
privateJButtonbutton3;
privateJButtonbutton4;
privateJButtonbutton5;
//在构造界⾯的时候就进⾏初始化界⾯
publicMyJFrame(){
init();
}
//初始化界⾯
privatevoidinit()
{
//设置窗体
e(600,400);//设置窗体⼤⼩
ationRelativeTo(null);//设置窗体居中显⽰
le("Java⽹格布局管理器⽰例");//设置窗体标题
aultCloseOperation(EXIT_ON_CLOSE);//设置点击窗体x号时退出程序
//为按钮引⽤创建按钮对象
button1=newJButton("按钮1");
button2=newJButton("按钮2");
button3=newJButton("按钮3");
button4=newJButton("按钮4");
//获取Frame界⾯容器
Containercontainer=tentPane();
out(newGridLayout(2,2));
//向Frame的容器中加⼊按钮组件
(button1);
(button2);
(button3);
(button4);
}
publicstaticvoidmain(String[]args){
MyJFrameframe=newMyJFrame();
ible(true);
}
}
当划分的⽹格数量与实际添加到窗体的组件数量不⼀致时:
(1)划分的⽹格较多,实际添加到窗体的组件的数量较少
(2)实际添加到窗体的组件的数量较多,划分的⽹格较多
总结:
所有⽹格⼤⼩都完全相同
所有添加到窗体上的组件都会被显⽰出来
⾏数不变列数变(如上组件数量少于⽹格数量,但是⾏数仍然为5,列数被虚拟机灵活地进⾏调整)
组件按照从左上到右下的顺序排列
4.事件处理
(1)事件处理的原理
事件源:
可以被操作,并能产⽣状态变化的组件
事件源可能产⽣多种类型的事件
监听器
负责监控事件源的状态,并在产⽣事件后负责处理事件
任何监听器只能处理特定类型的事件
监听器中的处理事件的⽅法都被定义成抽象⽅法
事件源和监听器的关系
事件源只有添加了监听器,监听器才在事件产⽣之后执⾏相应的处理代码
ner;
vent;
istener;
n;
;
publicclassMyJFrameextendsJFrame{
//创建按钮的引⽤
privateJButtonbutton1;
privateJButtonbutton2;
//在构造界⾯的时候就进⾏初始化界⾯
publicMyJFrame(){
init();
}
//初始化界⾯
privatevoidinit()
{
//设置窗体
e(600,400);//设置窗体⼤⼩
ationRelativeTo(null);//设置窗体居中显⽰
le("Java⽹格布局管理器⽰例");//设置窗体标题
aultCloseOperation(EXIT_ON_CLOSE);//设置点击窗体x号时退出程序
//为按钮引⽤创建按钮对象
button1=newJButton("按钮1");
button2=newJButton("按钮2");
//获取Frame界⾯容器
Containercontainer=tentPane();
//设置容器布局为绝对布局,即组件的摆放不受任何限制
out(null);
//为按钮设置位置和⼤⼩
ation(0,0);
e(200,100);
nds(100,150,200,100);
//为按钮1添加⿏标事件监听器
seListener(newMouseListener(){//什么监听器就是什么Listener
@Override
publicvoidmouseReleased(MouseEvente){//⿏标抬起,执⾏此⽅法
n("⿏标抬起");
}
@Override
publicvoidmousePressed(MouseEvente){//⿏标按下,执⾏此⽅法
n("⿏标按下");
}
@Override
publicvoidmouseExited(MouseEvente){//⿏标离开组件区域,执⾏此⽅法
//TODOAuto-generatedmethodstub
}
@Override
publicvoidmouseEntered(MouseEvente){//⿏标进⼊组件区域,执⾏此⽅法
//TODOAuto-generatedmethodstub
}
@Override
publicvoidmouseClicked(MouseEvente){//⿏标点击组件,执⾏此⽅法
//TODOAuto-generatedmethodstub
}
});
//向Frame的容器中加⼊按钮组件
(button1);
(button2);
}
publicstaticvoidmain(String[]args){
MyJFrameframe=newMyJFrame();
ible(true);
}
}
⿏标按下按钮1后:⿏标松开后:
分析:
事件源组件(如button1)都有添加监听器的⽅法(如addMouseListener(),⽽在⽅法中传递的是⼀个监听器(如MouseListener),这
个监听器监听着⼀些事件的发⽣,Java本⾝对于这些监听器的实现是⼀个接⼝,定义事件的抽象⽅法,统⼀接⼝,然后由程序,⾃⼰来实现
监听器中监听事件的⾏为,这样也就做到了通过统⼀的接⼝引⽤去调⽤不相同的具体实现⽅法,从⽽让事件的处理有⼀个统⼀的标准,统⼀
的模式
(2)常⽤监听器
除过ActionListener,其他监听器,我们基本看到它的名字就知道它监听的事件类型
ActionListener:
处理每个组件发⽣频率最⾼事件的监听器,如按钮发⽣最频繁的是点击事件,所以button的ActionListener⽤来处理点击事件
它当中只定义了⼀个抽象⽅法:
ner;
Event;
Listener;
n;
;
publicclassMyJFrameextendsJFrame{
//创建按钮的引⽤
privateJButtonbutton1;
privateJButtonbutton2;
//在构造界⾯的时候就进⾏初始化界⾯
publicMyJFrame(){
init();
}
//初始化界⾯
privatevoidinit()
{
//设置窗体
e(600,400);//设置窗体⼤⼩
ationRelativeTo(null);//设置窗体居中显⽰
le("Java⽹格布局管理器⽰例");//设置窗体标题
aultCloseOperation(EXIT_ON_CLOSE);//设置点击窗体x号时退出程序
//为按钮引⽤创建按钮对象
button1=newJButton("按钮1");
button2=newJButton("按钮2");
//获取Frame界⾯容器
Containercontainer=tentPane();
//设置容器布局为绝对布局,即组件的摆放不受任何限制
out(null);
//为按钮设置位置和⼤⼩
ation(0,0);
e(200,100);
nds(100,150,200,100);
//为按钮1添加⿏标事件监听器
ionListener(newActionListener(){
@Override
publicvoidactionPerformed(ActionEvente){
n("按钮被点击:actionPerformed");
}
});
//向Frame的容器中加⼊按钮组件
(button1);
(button2);
}
publicstaticvoidmain(String[]args){
MyJFrameframe=newMyJFrame();
ible(true);
}
}
使⽤ActionListener的优点:
当我们只需要为组件添加使⽤频率最⾼的那个监听事件时
1.可以节省实现其他监听事件的代码
2.可以使⽤Lambda表达式简化代码
⼀个组件是否可以添加多个监听器?
ner;
Event;
Listener;
n;
;
publicclassMyJFrameextendsJFrame{
//创建按钮的引⽤
privateJButtonbutton1;
privateJButtonbutton2;
//在构造界⾯的时候就进⾏初始化界⾯
publicMyJFrame(){
init();
}
//初始化界⾯
privatevoidinit()
{
//设置窗体
e(600,400);//设置窗体⼤⼩
ationRelativeTo(null);//设置窗体居中显⽰
le("Java⽹格布局管理器⽰例");//设置窗体标题
aultCloseOperation(EXIT_ON_CLOSE);//设置点击窗体x号时退出程序
//为按钮引⽤创建按钮对象
button1=newJButton("按钮1");
button2=newJButton("按钮2");
//获取Frame界⾯容器
Containercontainer=tentPane();
//设置容器布局为绝对布局,即组件的摆放不受任何限制
out(null);
//为按钮设置位置和⼤⼩
ation(0,0);
e(200,100);
nds(100,150,200,100);
//为按钮1添加2个事件监听器
ionListener(newActionListener(){
@Override
publicvoidactionPerformed(ActionEvente){
n("按钮被点击:actionPerformed1");
}
});
ionListener(newActionListener(){
@Override
publicvoidactionPerformed(ActionEvente){
n("按钮被点击:actionPerformed2");
}
});
//向Frame的容器中加⼊按钮组件
(button1);
(button2);
}
publicstaticvoidmain(String[]args){
MyJFrameframe=newMyJFrame();
ible(true);
}
}
分析:
可以为⼀个组件添加多个监听器,可以通过添加监听器⽅法中的源代码发现,添加组件时,会产⽣⼀个监听器的列表,每当添加组件,就会
将它加⼊到列表当中,当产⽣事件的时候,虚拟机会把组件的该列表中的所有监听器的事件⽅法都执⾏⼀遍,并且后添加到列表的监听器的
代码会先被执⾏
同⼀个监听器是否可以添加到多个组件中?
ner;
Event;
Listener;
n;
;
publicclassMyJFrameextendsJFrame{
//创建按钮的引⽤
privateJButtonbutton1;
privateJButtonbutton2;
//在构造界⾯的时候就进⾏初始化界⾯
publicMyJFrame(){
init();
}
//初始化界⾯
privatevoidinit()
{
//设置窗体
e(600,400);//设置窗体⼤⼩
ationRelativeTo(null);//设置窗体居中显⽰
le("Java⽹格布局管理器⽰例");//设置窗体标题
aultCloseOperation(EXIT_ON_CLOSE);//设置点击窗体x号时退出程序
//为按钮引⽤创建按钮对象
button1=newJButton("按钮1");
button2=newJButton("按钮2");
//获取Frame界⾯容器
Containercontainer=tentPane();
//设置容器布局为绝对布局,即组件的摆放不受任何限制
out(null);
//为按钮设置位置和⼤⼩
ation(0,0);
e(200,100);
nds(100,150,200,100);
ActionListenerae=newActionListener(){
@Override
publicvoidactionPerformed(ActionEvente){
n("按钮被点击:actionPerformed1");
}
};
//为按钮1和2添加相同事件监听器
ionListener(ae);
ionListener(ae);
//向Frame的容器中加⼊按钮组件
(button1);
(button2);
}
publicstaticvoidmain(String[]args){
MyJFrameframe=newMyJFrame();
ible(true);
}
}
点击按钮1和2都执⾏相同⽅法
结论:⼀个监听器可以同时监听多个组件的变化,对这些组件的事件做相同的处理
委托事件模型(或授权事件模型)
事件源和监听器这种关系就是委托事件模型,即事件源发⽣的事件,事件源本⾝不去处理,⽽授权给监听器去处理
5.监听器的多种实现⽅式
为什么要研究监听器的实现⽅式?
关系到组件的访问权限问题
涉及到数据安全问题
监听器的实现⽅式:
匿名内部类实现
普通内部类实现
窗体实现监听器类接⼝
外部类实现
(1)匿名内部类实现
需求:点击button1按钮的时候在button2按钮上显⽰button1被点击的次数
ner;
Event;
Listener;
n;
;
publicclassMyJFrameextendsJFrame{
//创建按钮的引⽤
privateJButtonbutton1;
privateJButtonbutton2;
//在构造界⾯的时候就进⾏初始化界⾯
publicMyJFrame(){
init();
}
//初始化界⾯
privatevoidinit()
{
//设置窗体
e(600,400);//设置窗体⼤⼩
ationRelativeTo(null);//设置窗体居中显⽰
le("匿名内部类实现⽰例");//设置窗体标题
aultCloseOperation(EXIT_ON_CLOSE);//设置点击窗体x号时退出程序
//为按钮引⽤创建按钮对象
button1=newJButton("按钮1");
button2=newJButton("按钮2");
//获取Frame界⾯容器
Containercontainer=tentPane();
//设置容器布局为绝对布局,即组件的摆放不受任何限制
out(null);
//为按钮设置位置和⼤⼩
ation(0,0);
e(200,100);
nds(100,150,200,100);
ionListener(newActionListener(){
intclick_count=0;
@Override
publicvoidactionPerformed(ActionEvente){
++click_count;
t("button1被点击了"+click_count+"次");
}
});
//向Frame的容器中加⼊按钮组件
(button1);
(button2);
}
publicstaticvoidmain(String[]args){
MyJFrameframe=newMyJFrame();
ible(true);
}
}
分析:
我们遇到的问题:
问题1.监听器需要修改窗体类的私有属性
解决办法:把监听器设计为“内部”类对象
问题2:监听器必须不能被重复使⽤,即组件button1的监听器只⽤来监听button1,不能被⽤来监听其他组件
解决办法:把监听器设计为⼀个匿名类对象(⼀个匿名类只能有⼀个对象,没有⽤任何的引⽤去指向它,⽽是直接把它传递给⽅法)
为什么不采⽤如下的写法?
此种写法产⽣了⼀个指向监听器的引⽤al,引⽤的存在会产⽣通过引⽤重复使⽤监听器对象的可能性
结论:⼀个匿名内部类实现代码保证了只能被⽤来创建⼀个监听器对象,被⼀个组件使⽤,并且能访问类的私有属性
此种⽅式的特点:
操作窗体组件容易
监听器对象复⽤程度最低
安全性最⾼
代码结构复杂
(2)普通内部类的实现
需求:窗体上有10个按钮,每个按钮被点击的时候,都把该按钮的点击次数显⽰到button2上(下⾯的⽰例⽤2个被点击的按钮做演⽰)
匿名内部类实现⽅式:
需要给每个按钮都添加监听器,需要给每个按钮都添加匿名内部类
可以发现,如果这样把10个都写完,代码⾮常臃肿,它们仅仅时button1和button2这样的字符串不同,我们可以对它们的共性进⾏提取,
使⽤普通内部类来实现
ner;
Event;
Listener;
n;
;
publicclassMyJFrameextendsJFrame{
//创建按钮的引⽤
privateJButtonbutton1;
privateJButtonbutton2;
privateJButtonbutton3;
//在构造界⾯的时候就进⾏初始化界⾯
publicMyJFrame(){
init();
}
//初始化界⾯
privatevoidinit()
{
//设置窗体
e(600,400);//设置窗体⼤⼩
ationRelativeTo(null);//设置窗体居中显⽰
le("普通内部类实现⽰例");//设置窗体标题
aultCloseOperation(EXIT_ON_CLOSE);//设置点击窗体x号时退出程序
//为按钮引⽤创建按钮对象
button1=newJButton("按钮1");
button2=newJButton("按钮2");
button3=newJButton("按钮3");
//获取Frame界⾯容器
Containercontainer=tentPane();
//设置容器布局为绝对布局,即组件的摆放不受任何限制
out(null);
//为按钮设置位置和⼤⼩
ation(0,0);
e(200,100);
nds(100,150,200,100);
nds(400,250,100,100);
classActionListenerImpimplementsActionListener{
classActionListenerImpimplementsActionListener{
StringbuttonName;
intclick_count=0;
publicActionListenerImp(StringbuttonName){
Name=buttonName;
}
@Override
publicvoidactionPerformed(ActionEvente){
++click_count;
t(buttonName+"被点击了"+click_count+"次");
}
}
ionListener(newActionListenerImp("button1"));
ionListener(newActionListenerImp("button3"));
//向Frame的容器中加⼊按钮组件
(button1);
(button2);
(button3);
}
publicstaticvoidmain(String[]args){
MyJFrameframe=newMyJFrame();
ible(true);
}
}
按钮1和按钮2有各⾃的监听器对象,但通过向构造⽅法中传参的⽅式复⽤了同⼀段代码
使⽤匿名类传⼊到添加监听器的⽅法中⼜保证了⼀个监听器对象不能被其他组件复⽤,每个组件有各⾃独⽴的监听器对象
结论:⼀个普通内部类实现代码使得可以创建多个对象,通过传参进⾏区别,然后通过匿名对象保证监听器对象只能被⼀个组件使⽤
(3)窗体实现监听器类接⼝
需求同上
ner;
Event;
Listener;
n;
;
publicclassMyJFrameextendsJFrameimplementsActionListener{
//创建按钮的引⽤
privateJButtonbutton1;
privateJButtonbutton2;
privateJButtonbutton3;
//定义⼀个计数器
//定义⼀个计数器
privateintbutton1_count;
privateintbutton3_count;
//在构造界⾯的时候就进⾏初始化界⾯
publicMyJFrame(){
init();
}
//初始化界⾯
privatevoidinit()
{
//设置窗体
e(600,400);//设置窗体⼤⼩
ationRelativeTo(null);//设置窗体居中显⽰
le("窗⼝实现监听器接⼝⽰例");//设置窗体标题
aultCloseOperation(EXIT_ON_CLOSE);//设置点击窗体x号时退出程序
//为按钮引⽤创建按钮对象
button1=newJButton("按钮1");
button2=newJButton("按钮2");
button3=newJButton("按钮3");
//获取Frame界⾯容器
Containercontainer=tentPane();
//设置容器布局为绝对布局,即组件的摆放不受任何限制
out(null);
//为按钮设置位置和⼤⼩
ation(0,0);
e(200,100);
nds(100,150,200,100);
nds(400,250,100,100);
//添加监听器
ionListener(this);
ionListener(this);
//向Frame的容器中加⼊按钮组件
(button1);
(button2);
(button3);
}
publicstaticvoidmain(String[]args){
MyJFrameframe=newMyJFrame();
ible(true);
}
//监听器接⼝的⽅法
@Override
publicvoidactionPerformed(ActionEvente){
if(rce()==button1)
{
++button1_count;
t("button1被点击了"+button1_count+"次");
}
elseif(rce()==button3)
{
++button3_count;
t("button3被点击了"+button3_count+"次");
}
}
}
这种写法的缺点:
1.窗体的⾓⾊过于复杂,如果需要其他监听器,还要实现多个监听器的⽅法
2.不同事件源共⽤⼀个处理⽅法,如上button1和button2共⽤了⼀个处理⽅法
3.代码臃肿,可读性极差
4.代码的安全性较差,因为监听器接⼝的⽅法被定义为public,当我们实现该接⼝的时候不能降低访问权限,这样外部类对象也可以访
问监听器的事件处理⽅法,⾮常不安全
这种写法不推荐,弊⼤于利
(4)外部类实现
需求同上
Event;
Listener;
n;
publicclassButtonActionListenerimplementsActionListener{
//在这个⽅法中要操作某个窗体中的组件,我们不能为actionPerformed⽅法传参来操作它
//我们可以类定义⼀个窗体的引⽤,然后通过构造⽅法传⼊到监听器当中
privateMyJFrameframe;
privateStringbutton_Name;
privateintcount;
publicButtonActionListener(MyJFrameframe,Stringbutton_Name){
super();
=frame;
_Name=button_Name;
}
@Override
publicvoidactionPerformed(ActionEvente){
count++;
//我们没有办法直接访问MyJFrame中的私有属性,只能通过MyJFrame提供get⽅法或提升button的访问权限来访问它
t(button_Name+"被点击了"+count+"次");
}
}
ner;
Event;
Listener;
n;
;
publicclassMyJFrameextendsJFrame{
//创建按钮的引⽤
privateJButtonbutton1;
publicJButtonbutton2;
privateJButtonbutton3;
//在构造界⾯的时候就进⾏初始化界⾯
publicMyJFrame(){
init();
}
//初始化界⾯
privatevoidinit()
{
//设置窗体
e(600,400);//设置窗体⼤⼩
ationRelativeTo(null);//设置窗体居中显⽰
le("外部类实现⽰例");//设置窗体标题
aultCloseOperation(EXIT_ON_CLOSE);//设置点击窗体x号时退出程序
//为按钮引⽤创建按钮对象
button1=newJButton("按钮1");
button2=newJButton("按钮2");
button3=newJButton("按钮3");
//获取Frame界⾯容器
Containercontainer=tentPane();
//设置容器布局为绝对布局,即组件的摆放不受任何限制
out(null);
//为按钮设置位置和⼤⼩
ation(0,0);
e(200,100);
nds(100,150,200,100);
nds(400,250,100,100);
//添加监听器
ionListener(newButtonActionListener(this,"button1"));
ionListener(newButtonActionListener(this,"button3"));
//向Frame的容器中加⼊按钮组件
(button1);
(button2);
(button3);
}
publicstaticvoidmain(String[]args){
MyJFrameframe=newMyJFrame();
ible(true);
}
}
优点:
1.代码结构清晰,监听器和窗体完全独⽴
2.监听器复⽤程度最⾼
缺点:
监听器在访问组件的时候会受到组件访问度的限制
我们需要提升窗体中要被监听器访问组件的权限,安全性较差
各种写法各有利弊,根据业务需求进⾏选择