从今天开始的这几天,我主要讲java的GUI编程。
图形用户界面(Graphics user interface, GUI)是指用图形的方式,借助菜单、按钮等标准界面元素和鼠标操作,帮助用户方便地向计算机系统发出指令、启动操作,并将系统运行的结果以图形方式显示给用户的技术。
由于用户界面设计质量的好坏直接影响软件的使用,Java语言对此也十分重视,几乎在JDK每个新的版本中,都增加了一定的GUI程序设计新技术或功能,Java语言的GUI发展始终保持着较好的连贯性和兼容性。
目前Java主要提供了两个处理图形用户界面的类库:java.awt和javax.swing。
AWT:抽象窗口工具集(Abstract Windows Toolkit),由于Java代码可以在不同的系统平台运行,而不同平台的图形界面外观设计各有差异,所以Java程序的图形用户界面在不同的平台上可能出现不同的运行效果,其外观取决于具体的平台,所以称AWT是一个抽象的工具集。
Swing:Swing是在AWT的基础上构建的,提供了比标准AWT组件更强大和灵活的功能。与AWT组件不同的是,Swing组件不是由特定的平台代码实现,而是纯粹的Java代码,因此能够实现与平台的无关(此类组件一般被称为轻量级组件)。
利用GUI类库设计和实现图形用户界面的工作主要有两个:一是应用的外观设计,即创建组成图形界面的各部件,指定其位置和属性关系,根据需要进行排列,从而构成完整的图形用户界面的物理外观;二是与用户的交互处理,包括定义图形用户界面的事件以及各部件对不同时间的响应处理。
那现在开始就先讲AWT。AWT类包含在java.awt包中,主要包括用户界面组件、事件处理模型、图形和图像工具、布局管理器等。Java.awt包中的主要类及组件类的继承关系如图
先来个最简单的例子,eg
-
- public class TestPanel
- {
- public static void main(String[] args)
- {
- Frame f = new Frame("测试窗口");
- //创建一个Panel对象
- Panel p = new Panel();
- //相Panel对象中添加两个组件
- p.add(new TextField(20));
- p.add(new Button("单击我"));
- f.add(p);
- //设置窗口的大小、位置
- f.setBounds(30, 30 , 250, 120);
- //将窗口显示出来(Frame对象默认处于隐藏状态)
- f.setVisible(true);
- }
- }
然后我讲下布局管理器AWT中分为
FlowLayout
BorderLayout
CardLayout
GridLayout
GridBagLayout
这五种
Swing的话再加上BoxLayout
顺序布局(FlowLayout)是Panel容器的缺省布局策略,即将加入容器中的组件依次从左至右,从上至下排列,适用于组件个数较少的情况。eg
- public class TestFlowLayout
- {
- public static void main(String[] args)
- {
- Frame f = new Frame("测试窗口");
- //设置Frame容器使用FlowLayout布局管理器
- f.setLayout(new FlowLayout(FlowLayout.LEFT , 20, 5));
- //向窗口中添加10个按钮
- for (int i = 0; i < 10 ; i++ )
- {
- f.add(new Button("按钮" + i));
- }
- //设置窗口为最佳大小
- f.pack();
- //将窗口显示出来(Frame对象默认处于隐藏状态)
- f.setVisible(true);
- }
- }
pack()方法非常有用,能讲窗口调整到最佳大小
边界布局(BorderLayout)是Frame,Dialog,ScrollPane的缺省布局。区域布局将容器分为东西南北中五个区域,加入组件时,应通过字符串East/West /South/North/Center来标记组件的方位。eg
- public class TestBorderLayout
- {
- public static void main(String[] args)
- {
- Frame f = new Frame("测试窗口");
- //设置Frame容器使用BorderLayout布局管理器
- f.setLayout(new BorderLayout(30, 5));
- f.add(new Button("南") , BorderLayout.SOUTH);
- f.add(new Button("北") , BorderLayout.NORTH);
- //默认添加到中间
- f.add(new Button("中"));
- f.add(new Button("东") , BorderLayout.EAST);
- f.add(new Button("西") , BorderLayout.WEST);
- //设置窗口为最佳大小
- f.pack();
- //将窗口显示出来(Frame对象默认处于隐藏状态)
- f.setVisible(true);
- }
- }
卡片布局(CardLayout)将容器中的每一个组件当作一个卡片,一次仅有一个卡片可见,最初显示容器时,加入到容器的第一个组件可见。eg
- public class TestCardLayout
- {
- Frame f = new Frame("测试窗口");
- String[] names = {"第一张" , "第二张" , "第三张" , "第四张" , "第五张"};
- Panel pl = new Panel();
- CardLayout c = new CardLayout();
- public void init()
- {
- pl.setLayout(c);
- for (int i = 0 ; i < names.length ; i++)
- {
- pl.add(names[i] , new Button(names[i]));
- }
- Panel p = new Panel();
- //控制显示上一张的按钮
- Button previous = new Button("上一张");
- previous.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- c.previous(pl);
- }
- });
- //控制显示下一张的按钮
- Button next = new Button("下一张");
- next.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- c.next(pl);
- }
- });
- //控制显示第一张的按钮
- Button first = new Button("第一张");
- first.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- c.first(pl);
- }
- });
- //控制显示最后一张的按钮
- Button last = new Button("最后一张");
- last.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- c.last(pl);
- }
- });
- //控制根据Card名显示的按钮
- Button third = new Button("第三张");
- third.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- c.show(pl , "第三张");
- }
- });
- p.add(previous);
- p.add(next);
- p.add(first);
- p.add(last);
- p.add(third);
- f.add(pl);
- f.add(p , BorderLayout.SOUTH);
- f.pack();
- f.setVisible(true);
- }
- public static void main(String[] args)
- {
- new TestCardLayout().init();
- }
- }
网格布局(GridLayout)
将容器划分为n*m的大小相同的小格,每格区间可摆放一个组件。向容器中增加组件时,按从左至右,从上至下的顺序依次存放.eg
- public class TestGridLayout
- {
- public static void main(String[] args)
- {
- Frame f = new Frame("计算器");
- Panel p1 = new Panel();
- p1.add(new TextField(30));
- f.add(p1 , BorderLayout.NORTH);
- Panel p2 = new Panel();
- //设置Panel使用GridLayout布局管理器
- p2.setLayout(new GridLayout(3, 5 , 4, 4));
- String[] name = {"0" , "1" , "2" , "3" , "4" , "5" ,
- "6" , "7" , "8" , "9" , "+" , "-" , "*" , "/" , "."};
- //向Panel中依次添加15个按钮
- for (int i = 0 ; i < name.length; i++ )
- {
- p2.add(new Button(name[i]));
- }
- f.add(p2);
- //设置窗口为最佳大小
- f.pack();
- //将窗口显示出来(Frame对象默认处于隐藏状态)
- f.setVisible(true);
- }
- }
网格包布局(GridBagLayout)这个功能最强大,但用起来太麻烦了。将视图分为多个单元,可以指定每个组件占用的单元
GridBagConstraints类-参数:
gridx,gridy:组件的位置
gridwidth,gridheight:组件覆盖的网格单元个数
insets:组件和包含它的网格单元之间的距离
weightx,weighty:视图大小变化时,组件的情况,标准为100,0为组件占用空间不变
fill:填充方式,4种
anchor:组件在网格单元中的位置,CENTER/NORTH/NORTHWEST。eg
- public class TestGridBag
- {
- private Frame f = new Frame("测试窗口");
- private GridBagLayout gb = new GridBagLayout();
- private GridBagConstraints gbc = new GridBagConstraints();
- private Button[] bs = new Button[10];
- public void init()
- {
- f.setLayout(gb);
- for (int i = 0; i < bs.length ; i++ )
- {
- bs[i] = new Button("按钮" + i);
- }
- //所有组件都可以横向、纵向上扩大
- gbc.fill = GridBagConstraints.BOTH;
- gbc.weightx = 1;
- addButton(bs[0]);
- addButton(bs[1]);
- addButton(bs[2]);
- //该GridBagConstraints控制的GUI组件将会成为横向最后一个元素
- gbc.gridwidth = GridBagConstraints.REMAINDER;
- addButton(bs[3]);
- //该GridBagConstraints控制的GUI组件将横向上不会扩大
- gbc.weightx = 0;
- addButton(bs[4]);
- //该GridBagConstraints控制的GUI组件将横跨2个网格
- gbc.gridwidth = 2;
- addButton(bs[5]);
- //该GridBagConstraints控制的GUI组件将横跨1个网格
- gbc.gridwidth = 1;
- //该GridBagConstraints控制的GUI组件将纵向跨2个网格
- gbc.gridheight = 2;
- //该GridBagConstraints控制的GUI组件将会成为横向最后一个元素
- gbc.gridwidth = GridBagConstraints.REMAINDER;
- addButton(bs[6]);
- //该GridBagConstraints控制的GUI组件将横向跨越一个网格,纵向跨越2个网格。
- gbc.gridwidth = 1;
- gbc.gridheight = 2;
- //该GridBagConstraints控制的GUI组件纵向扩大的权重是1
- gbc.weighty = 1;
- addButton(bs[7]);
- //设置下面的按钮在纵向上不会扩大
- gbc.weighty = 0;
- //该GridBagConstraints控制的GUI组件将会成为横向最后一个元素
- gbc.gridwidth = GridBagConstraints.REMAINDER;
- //该GridBagConstraints控制的GUI组件将纵向上横跨1个网格
- gbc.gridheight = 1;
- addButton(bs[8]);
- addButton(bs[9]);
- f.pack();
- f.setVisible(true);
- }
- private void addButton(Button button)
- {
- gb.setConstraints(button, gbc);
- f.add(button);
- }
- public static void main(String[] args)
- {
- new TestGridBag().init();
- }
- }
盒子布局(BoxLayout)对GridBagLayout进行了简化,保留了它的优点。Box容器的默认布局管理就是它。它是通过横向或纵向放置器件。eg
- public class TestBoxSpace
- {
- private Frame f = new Frame("测试");
- //定义水平摆放组件的Box对象
- private Box horizontal = Box.createHorizontalBox();
- //定义垂直摆放组件的Box对象
- private Box vertical = Box.createVerticalBox();
- public void init()
- {
- horizontal.add(new Button("水平按钮一"));
- horizontal.add(Box.createHorizontalGlue());
- horizontal.add(new Button("水平按钮二"));
- //水平方向不可拉伸的间距,其宽度为10px
- horizontal.add(Box.createHorizontalStrut(10));
- horizontal.add(new Button("水平按钮三"));
- vertical.add(new Button("垂直按钮一"));
- vertical.add(Box.createVerticalGlue());
- vertical.add(new Button("垂直按钮二"));
- //垂直方向不可拉伸的间距,其高度为10px
- vertical.add(Box.createVerticalStrut(10));
- vertical.add(new Button("垂直按钮三"));
- f.add(horizontal , BorderLayout.NORTH);
- f.add(vertical);
- f.pack();
- f.setVisible(true);
- }
- public static void main(String[] args)
- {
- new TestBoxSpace().init();
- }
- }