AWT编程基础
关于AWT和Swing的一些介绍
Java使用AWT和Swing类完成图形用户界面编程。
AWT的全称是抽象窗口工具集(Abstract Window Toolkit),是最早提供的GUI库,该GUI库提供了一些基本功能,但功能有限,所以又提供了Swing库。
AWT是窗口框架,从不同平台的窗口系统中取出共同组件,当程序运行时,将这些组件的创建和动作委托给程序所在的平台。即当使用AWT编写图形界面应用时,程序仅指定了界面组件的位置和行为,并未提供真正的实现,JVM调用操作系统本地的图形界面来创建和平台一致的对等体。
使用AWT创建的图形界面应用和所在的运行平台有相同的界面风格(比如在Windows操作系统上就表现出Windows风格)
AWT出现了以下的问题
1.使用AWT做出的图形用户界面比较丑陋,且功能有限
2.AWT为了迎合所有主流操作系统的平面设计,AWT组件只能使用这些操作系统上图形界面组件的交集,所以不能使用特定操作系统上复杂的图形界面组件,最多只能使用4种字体
AWT使用的是非面向对象的编程模式
Swing组件在一定程度上替代了AWT的组件,但并没有完全替代AWT,是建立在AWT的基础上提供了能力更强的用户界面组件,即使是完全使用Swing编写的GUI程序,也依然需要使用AWT的事件处理机制。
所有和AWT编程相关的类都放在java.awt包以及它的子包中
AWT编程中有两个基类:Component和MenuComponent。
Component代表一个能以图形化方式显示出来,并可以和用户交互的对象(例如Button,一个按钮)。
MenuComponent则代表图形界面的菜单组件。(例如菜单条)
AWT编程中还有两个重要的概念:Container和LayoutManager。
Container是一种特殊的Component,代表一种容器,可以盛装普通的Component。
LayoutManager则是容器管理其他组件布局的方式。
AWT容器
容器
容器(Container)是Component的子类,因此容器本身也是一个组件,具有组件的所有性质,可以调用Component类的所有方法。
Component类提供了一些常用方法来设置组件的大小、位置和可见性等。
setLoction(int x ,int y):设置组件的位置
setSize(int width, int height):设置组件的大小
setBounds(int x,int y,int width,int height):同时设置组件的位置、大小
setVisible(Boolean b):设置该组件的可见性
容器还可以盛装其他组件,容器类(Container)类提供了如下常用方法来访问容器里的组件。
Component add(Componer comp):向容器中添加其他组件(该组件既可以是普通组件,也可以是容器),并返回被添加的组件
Component getComponentAt(int x,int y):返回指定的组件
int getComponentCount():返回该容器内的所有组件。
AWT主要提供如下两种主要的容器类型:
Window:可以独立存在的顶级窗口
Panel:可以作为容器容纳其他组件,但不能独立存在,必须被添加到其他容器中(如Window、Paneld等)
AWT容器的继承关系
Frame
Frame是常见的窗口,是Window类的子类,具有已下特点
1. Frame对象有标题,允许通过拖拉来改变窗口的位置、大小
2. 初始化时为不可见,可以通过调用setVisible()方法使其显示出来。
3. 默认使用Borderlayout作为其布局管理器。(下文会介绍)
代码举例:
import java.awt.*;
public class FrameTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame F = new Frame("Test Window");
F.setBounds(50, 50, 300, 300);//设置窗口大小
F.setVisible(true);//设置窗口为可见
}
}
结果:
此时为u发通过点右上角的×来关闭窗口,因为并没有添加相应的响应事件。
Panel
Panel代表一个不能独立存在,必须放在其他容器的容器。Panel外在表现为一个矩形区域,该区域可盛装其他组件。
Panel容器存在意义在于为其他组件提供空间。
Panel容器有如下几个特点:
1. 可以作为容器来盛装其他组件,为放置组件提供空间
2. 不能单独存在,必须放置到其他容器中
3. 默认使用FlowLayout作为其布局管理器
代码举例:
import java.awt.*;
public class PanelTest {
public static void main(String [] args)
{
Frame F = new Frame("Test Windoiw");
Panel P = new Panel();
//向Panel添加两个Button组件
P.add(new Button("Button1"));
P.add(new Button("Button2"));
//将Panel容器添加到Frame窗口中
F.add(P);
F.setBounds(50,50,300,300);
F.setVisible(true);
}
}
结果:
同样因为没有添加响应事件无法直接通关组件来关闭。
ScrollPane
ScrollPane是一个带滚动条的容器,不能独立存在,必须被添加到其他容器中
ScrollPane有以下的特点:
1. 可以作为容器来盛装其他组件,当组件占用空间过大时,ScrollPane自动产生滚动条。也可以通过指定特定的构造器参数来指定默认具有滚动条。
2. 不能单独存在,必须放置到其他容器中
3. 默认使用BorderLayout作为其布局管理器。
4. 由于通常用于盛装其他容器,所以通常不允许改边ScrollPane的布局管理器。
代码举例:
import java.awt.*;
public class ScrollPaneTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame F = new Frame("Test Window");
//创建ScrollPane容器,指定具有滚动条
ScrollPane SP = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS);
//添加组件
SP.add(new Button("Button"));
F.add(SP);
F.setBounds(50,50,300,300);
F.setVisible(true);
}
}
结果:
Box容器
主要配合BoxLayout布局管理器使用,后面详细介绍
布局管理器
什么是布局管理器
为了使生成的图形用户界面具有良好的平台无关性,Java提供了布局管理器这个工具来管理组件在容器中的布局,而不是使用直接设置组件位置和大小的方式。
例如通过语句定义了一个标签(Label)
Label L1 = new Label(“Hello Java”);
为了让L1标签刚好可以容纳这句字符串,即实现该标签的最佳大小(没有冗余空间也没有内容被遮挡)。在Windows是一个大小,在UNIX上可能又是另一个大小。涉及到程序跨平台移植时,程序需要做大量的工作来调整图形界面。
对于不同组件而言,它们都有一个最佳大小,这个最佳大小通常与平台有关,程序在不同的平台运行,相同的内容可能大小不一样。让程序员手动控制大小无疑增加了很多麻烦。为了解决这个问题,Java提供了LayoutManager,LayoutManager可以根据运行平台来调整组件大小,程序员则只需要为容器选择合适的布局管理器。
注意
1.所有的AWT容器都有默认的布局管理器,如果没有为容器指定布局管理器,则该容器使用默认的布局管理器。
2.为容器指定布局管理器可以通过调用容器对象的setLayout(LayoutManager lm)方法来完成
3.AWT提供了FlowLayout、Broadlayout、GridLayout、GridBagLayout、CardLayout5个常用的布局管理器,Swing还提供了一个BoxLayout布局管理器
FlowLayout布局管理器
默认情况下,FlowLayout布局管理器从左向右排列所有组件,遇到边界则会折回从下一行重新开始
FlowLayout的构造器
FlowLayout有三个构造器
1.FlowLayout():使用默认的对齐方式及默认的垂直间距、水平间距创建FlowLayout布局管理器
2.FlowLayout(int align):使用指定的对齐方式及默认的垂直间距、水平间距创建FlowLayout布局管理器
注:
align表明FlowLayout中组件的排列方向:从左到右,从右到左,从中间向两边等(所列三个最为常用),该参数使用FlowLayout类的静态常量:FlowLayout.LEFT、FlowLaoyout.RIGHT、FlowLayout.CENTER等
3.FlowLayout(int align ,int hgap,int vgap):使用指定的对齐方式及指定的垂直间距、水平间距创建FlowLayout布局管理器
注:
hgap、vgap代表水平间距、垂直间距,为两个参数传入整数值即可。
回忆:Panel和Applet默认使用FlowLayout布局管理器
代码举例:
import java.awt.*;
public class FlowLayoutTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame F = new Frame("Test Window");
//设置Frame容器使用FlowLayout布局管理器
//指定垂直间距和水平间距都为5
F.setLayout(new FlowLayout(FlowLayout.LEFT , 5 ,5));
//添加6个按钮
for(int temp = 0; temp < 6 ;temp++)
{
F.add(new Button("Button" + temp));
}
//调用pack()方法将窗口调整到最佳大小
F.pack();
F.setVisible(true);
}
}
结果:
BorderLayout布局管理器
BorderLayout将容器分为EAST、SOUTH、WEST、NORTH、CENTER五个区域,需要的组件可以放置在这五个区域的任意一个。
当使用BorderLayout改变其大小时,NORTH、SOUTH和CENTER区域是水平调整,EAST、WEST和CENTER区域垂直调整。
BorderLayout使用时需要注意以下两点:
1.当向使用BorderLayout布局管理器的容器中添加组件时,需要指定要添加到的区域(NORTH、WEST等),否则会默认添加到CENTER.
2.如果向同一个区域中添加多个组件时,后放入的组件会覆盖先放入的组件。
3.BorderLayout最多只能放置5个组件,若少于5个组件,某个区域没有放置组件时。该区域不会出现空白,旁边区域的组件会自动占据该区域,从而保证窗口有较好的外观。(但可以通过其他技巧,让BorderLayout容纳的组件数远超于5个,比如向Panel添加多个组件,再把Panel添加到BorderLayout中)
回忆:Frame、Dialog、ScrollPane默认使用BorderLayout布局管理器
BorderLayout的构造器
1.BorderLayout():使用默认的水平间距、垂直间距创建的BorderLayout布局管理器。
2.BorderLayout(int hgap, int vgap):使用指定的垂直间距、水平间距创建BorderLayout布局管理器。
代码举例1
import java.awt.*;
import static java.awt.BorderLayout.*;
public class BorderLayoutTest1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame F = new Frame("Test Window");
//使用BorderLayout布局管理器
F.setLayout(new BorderLayout(20, 20));
//添加5个按钮
F.add(new Button("NORTH") , NORTH);
F.add(new Button("SOUTH") , SOUTH);
F.add(new Button("EAST") , EAST);
F.add(new Button("WEST") , WEST);
//默认添加到CENTER区域
F.add(new Button("CENTER") );
F.pack();
F.setVisible(true);
}
}
结果:
代码举例2
import java.awt.*;
import static java.awt.BorderLayout.*;
public class BorderLayoutTest2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame F = new Frame("Test Window");
//使用BorderLayout布局管理器
F.setLayout(new BorderLayout(20, 20));
//添加两个组件
F.add(new Button("NORTH") , NORTH);
F.add(new Button("SOUTH") , SOUTH);
F.add(new Button("EAST") , EAST);
//创建一个Panel,且添加多个组件
Panel P = new Panel();
for(int temp = 0;temp < 4;temp++)
{
P.add(new Button("Button" + temp));
}
//默认将Panel添加到中间区域
F.add(P);
F.pack();
F.setVisible(true);
}
}
结果:
GridLayout布局管理器
GridLayout布局管理器将容器分割成纵横线分割的网格,每个网格所占的区域大小相同。使用Grid
Layout 布局管理器添加组件时,默认从左向右、从上向下一次添加到每个网格中。(与FlowLayout类似,但不同的是,放置在GridLayout布局管理器中的各个组件的大小由组件所处的区域来决定,每个组件会自动占满震哥哥区域)
GridLayout的构造器
1.GridLayout(int rows,int cols):采用指定的行数、列数,以及默认的横向间距、纵向间距将容器分割成多个网格(rows 代表行数、cols代表列数)
2.GridLayout(int rows,int cols,int hgap,int vgap):采用指定的行数、列数,以及指定的横向间距、纵向间距将容器分割成多个网格。
代码举例
import java.awt.*;
public class GridLayoutTest {
public static void main(String args[])
{
Frame F = new Frame("Test Window");
Panel P = new Panel();
//设置使用GridLayout布局管理器
P.setLayout(new GridLayout(3,3,15,15));
//依次添加9个按钮
for(int temp = 1;temp < 10;temp++)
{
P.add(new Button("" + temp + ""));
}
F.add(P);
F.pack();
F.setVisible(true);
}
}
结果:
GridBagLayout布局管理器
与GridLayout布局管理器一定程度上相似。但不同的在于GridBagLayout布局管理器中,一个组件可以跨越一个或多个网格,并且可以设置各网格的大小互不相同。
当窗口的大小发生变化时,GridLayout布局管理器也可以精确地控制窗口各部分的拉伸。
GridBagLayout的使用
GridBagLayout布局管理器的功能强大,但使用相对而言更复杂。
使用步骤一般如下
1. 创建GridBagLayout布局管理器,并指定GUI容器使用该布局管理器
2. 创建GridBagConstraints对象,并设置该对象的相关属性(用于设置受该对象控制的GUI组件的相关属性)
3. 调用GridBagLayout对象的方法来建立GridBagConstraints对象和受控制组件之间的关联
4. 添加组件,与采用普通布局管理器添加组件的方法完全一样
若需要添加多个GUI组件,则需要多次重复步骤2~4。
GridBagConstraints对象的常用属性
- gridx、gridy:设置受该对象控制的GUI组件左上角所在网格的横向索引、纵向索引。(GridBagConstraints左上角网格的索引为0,0)
该两值还可以是GridBagConstraints.RELATIVE(默认值),表明当前组件紧跟在上一个组件之后。- gridwidth、gridheight:设置受该对象控制的GUI组件横向、纵向可以跨越多少个网课,两个属性值的默认值为1。
如果设置两个属性值为GridBagConstraints.REMAINDER,表明受该对象控制的GUI组件是横向、纵向最后一个组件;
如果设置两个属性值为GridBagConstraints.RELATIVE,表明受该对象控制的GUI组件是横向、纵向倒数第二个组件- fill:设置受该对象控制的GUI组件如何占据空白区域。该属性的取值如下
GridBagConstraints.NONE: GUI组件不扩大
GridBagConstraints.HORIZONTAL: GUI组件水平扩大以占据空白区域
GridBagConstraints.VERTICAL: GUI组件垂直扩大以占据空白区域
GridBagConstraints.BOTH: GUI组件水平、垂直同时扩大以占据空白区域- ipadx、ipady:设置受该对象控制的GUI组件横向、纵向内部填充的大小,即在该组件最小尺寸的基础上还需增加多少。
如果设置了这两个属性,则组件的横向大小为最小宽度再加ipadx * 2像素,纵向大小为最小高度再加ipady * 2像素- insets: 设置受该对象控制的GUI组件的外部填充的大小,即该组件边界和显示区域边界之间的距离
- anchor:设置该对象控制的GUI组件在其显示区域中的定位方式。(可以参考BorderLayout协助记忆)
GridBagConstraints.CENTER 中间
GridBagConstraints. NORTH 上中
GridBagConstraints.NORTHWEST 左上角
GridBagConstraints.NORTHEAST 右上角
GridBagConstraints.SOUTH 下中
GridBagConstraints.SOUTHEAST 右下角
GridBagConstraints.SOUTHWEST 左下角
GridBagConstraints.EAST 右中
GridBagConstraints.WEST 左中- weightx、weighty:设置受该对象控制的GUI组件占据多余空间的水平、垂直增加比例(或称权重),这两个属性的默认值为0,即不占据多余的空间。
假设某容器水平线上有两个组件。且它们的水平权重为1、2,容器增加30个像素时,第一个组件宽度增加10像素,第二个增加20像素。
注意
如果希望某个控件的大小随容器的增加而增大,则必须同时设置控制该组件的GridBagConstraints对象的fill、weightx和weighty
代码举例:
import java.awt.*;
public class GridBagLayoutTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame F = new Frame("Test Window");
GridBagLayout GB = new GridBagLayout();
GridBagConstraints GBC = new GridBagConstraints();
//创建10个按钮
Button[] BS = new Button[10];
F.setLayout(GB);
for(int temp = 0;temp < BS.length ;temp++)
{
BS[temp] = new Button("Button" + temp);
}
//设置所有组件都可以在横向、纵向扩展
GBC.fill = GridBagConstraints.BOTH;
GBC.weightx = 1;
GBC.weighty = 1;
for(int temp = 0;temp < 3;temp++)
{
//建立GridBagConstraints对象和受控制组件之间的关联
GB.setConstraints(BS[temp], GBC);
F.add(BS[temp]);
}
//设置GridBagConstraints绑定的Button(BS[3])组件将会成为横向最后一个组件
GBC.gridwidth = GridBagConstraints.REMAINDER;
GB.setConstraints(BS[3], GBC);
F.add(BS[3]);
//设置GridBagConstraints绑定的Button(BS[4])组件横向上不会扩大
GBC.weightx = 0;
GB.setConstraints(BS[4], GBC);
F.add(BS[4]);
//设置GridBagConstraints绑定的Button(BS[5])组件横跨两个网格
GBC.gridwidth = 2;
GB.setConstraints(BS[5], GBC);
F.add(BS[5]);
//设置GridBagConstraints绑定的Button(BS[6])组件横跨一个网格
//纵向跨越两个网格且为横向最后一个元素
GBC.gridwidth = 1;
GBC.gridheight = 2;
GBC.gridwidth = GridBagConstraints.REMAINDER;
GB.setConstraints(BS[6], GBC);
F.add(BS[6]);
//设置GridBagConstraints绑定的Button(BS[7])组件横向跨越一个网格
//纵向跨越2个网格且纵向扩大的权重是1
GBC.gridwidth = 1;
GBC.gridheight = 2;
GBC.weighty = 1;
GB.setConstraints(BS[7], GBC);
F.add(BS[7]);
//设置下面的Button(BS[8],BS[9])在纵向上不会扩大
//为横向最后一个元素且将纵向上横跨一个网格
GBC.weighty = 0;
GBC.gridwidth = GridBagConstraints.REMAINDER;
GBC.gridheight = 1;
for(int temp = 8;temp < 10;temp++)
{
GB.setConstraints(BS[temp], GBC);
F.add(BS[temp]);
}
F.pack();
F.setVisible(true);
}
}
结果:
CardLayout布局管理器
CardLayout布局管理器是比较特殊的存在,它以时间而非空间来管理组件,比喻而言,它将加入的容器的所有组件看成一堆堆叠的扑克牌,每次只有最上面的那个牌(组件)可见
CardLayout的构造器
1. CardLayout():创建默认的CardLayout布局管理器
2. CardLayout(int hgap, int vgap):通过指定组件与容器左右边界的间距(hgap)、上下边界(vgap)的间距来创建CardLayout布局管理器
CardLayout控制控件的常用方法
1. first(Container target):显示target容器中的第一个组件
2. last(Container target):显示target容器中的最后一个组件
3. previous(Container target):显示target容器中的前一个组件
4. next(Container target):显示target容器中的后一个组件
5. show(Container target, String name):显示target容器中指定名字的组件
代码举例
import java.awt.*;
import java.awt.event.*;
public class CardLayoutTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame F = new Frame("Test Window");
String [] Names = {"Code_01","Code_02","Code_03","Code_04","Code_05"};
Panel PL = new Panel();
CardLayout CL = new CardLayout();
PL.setLayout(CL);
//向PL里面添加5个按钮,且指定组件名称
for(int temp = 0;temp < Names.length ; temp++)
{
PL.add(Names[temp] ,new Button(Names[temp])) ;
}
Panel P = new Panel();
//使用Lambda表达式为待会儿添加的按钮组件建立响应事件
ActionListener listener = e->
{
switch(e.getActionCommand())
{
case "Previous":
CL.previous(PL);
break;
case "Next":
CL.next(PL);
break;
case "First":
CL.first(PL);
break;
case "Last":
CL.last(PL);
break;
case "Show(Code_03)":
CL.show(PL, "Code_03");
break;
}
};
//显示上一个按钮
Button previous = new Button("Previous");
previous.addActionListener(listener);
//控制显示下一个按钮
Button next = new Button("Next");
next.addActionListener(listener);
//控制显示第一个按钮
Button first = new Button("First");
first.addActionListener(listener);
//控制显示最后一个按钮
Button last = new Button("Last");
last.addActionListener(listener);
//控制根据组件名显示的按钮
Button show = new Button("Show(Code_03)");
show.addActionListener(listener);
P.add(previous);
P.add(next);
P.add(first);
P.add(last);
P.add(show);
F.add(PL);
F.add(P , BorderLayout.SOUTH);
F.pack();
F.setVisible(true);
}
}
结果:
因为添加了响应效果无法完全展示,只展示初始结果:
BoxLayout布局管理器
由于GridBagLayout布局管理器的功能虽然强大,但其过于复杂,Swing引入了BoxLayout,BoxLayout保留了GridBagLayout的很多优点,但相对而言没有GridBagLayout那么复杂。BoxLayout可以在垂直和水平方向上摆放GUI组件,通常和Box容器结合使用
Box容器
Box默认使用BoxLayout布局管理器,一定程度上类似于Panel容器。获得一个Box容器后可以使用其来盛装普通的GUI组件,然后再将Box组件添加到其他组件中
创建Box对象
Box提供了两个静态方法
createHorizontalBox():创建一个水平排列的Box容器
createVerticalBox():创建一个垂直排列的Box容器
BoxLayout的构造器
BoxLayout(Container target, int axis):指定创建基于target容器的布局管理器,该布局管理器里的组件按axis方向排列。
BoxLayout.X_AXIS :横向
BoxLayout.Y_AXIS:纵向
BoxLayout调整组件间的间距
BoxLayout没有提供设置组件之间的构造器和方法,而是通过Box提供的静态方法创建Glue(橡胶)、Strut(支架)和RigidArea(刚性区域)来现实相关操作。
- Glue代表可以在横、纵向两个方向上同时拉伸的空白组件间距。
- Strut代表可以在横、纵向两个方向上中任一方向拉伸的空白组件间距。
- RigidArea代表不可拉伸的空白组件(间距)。
Box提供如下几个常用静态方法:
- createGlue():创建一条水平Glue(可以在两个方向同时拉伸的间距),返回Component对象
- createHorizontalGlue():创建一条水平Glue(可以在两个方向同时拉伸的间距),返回Component对象
- createVerticalGlue():创建一条垂直Glue(可以在两个方向同时拉伸的间距),返回Component对象
- createHorizontalStrut(int width):创建一条指定宽度的水平Strut(可以在垂直方向上拉伸的间距),返回Component对象
- createVerticalStrut(int width):创建一条指定宽度的垂直Strut(可以在水平方向上拉伸的间距),返回Component对象。
- createRigidArea(Dimension d):创建指定宽度、高度的RigidArea(不可拉伸的间距)返回Component对象。
代码举例
import java.awt.*;
import javax.swing.*;
public class BoxLayoutTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame F = new Frame("TestWindow");
//定义水平摆放组件的Box对象
Box HorBox = Box.createHorizontalBox();
//定义垂直摆放组件的Box对象
Box VerBox = Box.createVerticalBox();
HorBox.add(new Button("HorizontalButton1"));
HorBox.add(Box.createHorizontalGlue());
HorBox.add(new Button("HorizontalButton2"));
//水平方向不可拉伸的间距为15px
HorBox.add(Box.createHorizontalStrut(15));
HorBox.add(new Button("HorizontalButton3"));
VerBox.add(new Button("VerticalButton1"));
VerBox.add(Box.createVerticalGlue());
VerBox.add(new Button("VerticalButton2"));
//垂直方向不可拉伸的间距为15px
VerBox.add(new Button("VerticalButton3"));
F.add(HorBox , BorderLayout.SOUTH);
F.add(VerBox);
F.pack();
F.setVisible(true);
}
}
结果
绝对布局(绝对定位)
使用绝对定位相对而言会具有很高的灵活性(可以随意拖动组件、组件相互重叠等),但代价是可能导致GUI界面失去跨平台特性
绝对定位的使用
1. 将Container的布局管理器设成null: setLayout(null)
2. 向容器添加组件时,需调用setSize()或者setBounds()设置组件的大小、位置(也可以直接创建GUI组件时通过构造参数指定该组件的大小、位置,然后添加到容器中)
代码举例
import java.awt.*;
public class NullLayoutTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame F = new Frame("TestWindow");
Button B1 = new Button("1");
Button B2 = new Button("2");
Button B3 = new Button("3");
//使用绝对布局
F.setLayout(null);
//手动设置三个按钮的大小、位置
B1.setBounds(20,30,90,100);
B2.setSize(100, 100);
B3.setBounds(30,40,100,110);
F.add(B1);
F.add(B2);
F.add(B3);
F.setSize(200, 200);
F.setVisible(true);
}
}
结果
1对应B1,后面是B2,右上角是B3.窗口大小固定