您的位置: 网站首页 > 程序开发 > Java程序设计 > 第10章 图形用户界面 > 【10.3 布 局 管 理】

10.3 布 局 管 理

 

10.3  布 局 管 理

复杂的GUI要求其中的每一个组件都放置到精确的位置。它们通常由多个面板组成,每个面板上的组件都按指定的顺序排列。Java利用布局管理器来帮助设计人员安排容器上的组件。

10.3.1  布局管理器概述

在Java中,将组件置于容器上的方式可能与GUI系统有所不同。首先,所有东西都是程序代码,没有所谓“资源”用来控制组件位置;其次,组件摆放在容器上的方式并不是通过绝对定位,而是通过“布局管理器(Layout Manager)”来安排。布局管理器会依据组件的加入顺序决定其摆放方式。组件的大小、形状和位置在不同的布局管理器下有显著的不同。此外,布局管理器会自动适应小程序或应用程序窗口的大小,所以如果某个窗口的大小改变了,那么其上各个组件的大小、形状和位置都有可能发生改变。

Java提供以下几种布局管理器:流布局(FlowLayout)、网格布局(GridLayout)、边界布局(BorderLayout)、卡片布局(CardLayout)和手工布局管理器。这里主要讲述流布局、网格布局、边界布局和卡片布局。可以利用容器类setLayout方法为容器设置布局管理器。

10.3.2  布局管理器类

1.流布局(FlowLayout)

FlowLayout管理器是Panel和Applet 的默认布局管理器。其组件的放置规律是从上到下、从左到右,如果容器足够宽,第一个组件先添加到容器中第一行的最左边,后续的组件依次添加到上一个组件的右边,如果当前行已放置不下该组件,则放置到下一行的最左边。

FlowLayout类提供的构造方法主要有以下几个。

·    public FlowLayout( ):创建居中对齐、水平和垂直间距为5像素的FlowLayout对象。

·    public FlowLayout(int align):以指定的对齐方式创建水平和垂直间距为5像素的FlowLayout对象。

·    public FlowLayout(int align, int hgap, int vgap):以指定的对齐方式、水平和垂直间距创建FlowLayout对象。

FlowLayout中的对齐方式有3种:FlowLayout.LEF(左对齐)、FlowLayout.RIGHT(右对齐)和FlowLayout.CENTER(中央对齐)。

【例10-1】本例中的MyFlowLayout类演示了对3个按钮的简单管理效果。程序文件名为MyFlowLayout.java。

import java.awt.*;

//定义处理窗口事件的类CloseFrame,实现WindowListener接口

class CloseFrame implements WindowListener

{

      public void windowClosing(WindowEvent e)  {

        System.exit(1);

      } //退出系统

      public void windowActivated(WindowEvent e){}

      public void windowDeactivated(WindowEvent e){}

      public void windowClosed(WindowEvent e){}

      public void windowOpened(WindowEvent e){}

      public void windowIconified(WindowEvent e){}

      public void windowDeiconified(WindowEvent e){}

}

class MyFlowLayout

{

      public static void main(String args[])

    {

        Frame f = new Frame();

        f.setLayout(new FlowLayout()); //设置窗体容器的布局管理器为流式管理器

        Button button1 = new Button(" First");

        Button button2 = new Button("Second");

        Button button3 = new Button("Third");

        f.add(button1);

        f.add(button2);

        f.add(button3);

        f.addWindowListener(new CloseFrame());

        f.setSize(300,100);

        f.setVisible(true);

     }

}

运行效果如图10-4所示。

当容器的大小发生变化时,用FlowLayout 管理的组件会发生变化,其变化规律是:组件的大小不变,但是相对位置会发生变化。例如图10-4中3个按钮都处于同一行,如果把该窗口变窄,窄到刚好只能够放下一个按钮,则第二个按钮将折到第二行,第三个按钮将折到第三行。

图10-4  流布局

2.网格布局(GridLayout)

GridLayout 是一种网格状的布局,各个组件平均占据容器的空间。在生成GridLayout管理器对象时,需指明行数和列数,同时也可以指明各个组件之间的间距。当改变容器的大小时,其中的组件相对位置不变而大小改变,各个组件的排列方式为:从上到下、从左到右依次排列。

创建网格布局管理器对象常用下面两种构造方法来实现。

·    public GridLayout(int rows, int cols):以指定的行列数创建GridLayout对象。

·    public GridLayout(int rows, int cols, int hgap, int vgap):以指定的行列数与水平垂直间距创建GridLayout对象。

如果要创建一个行数固定的GridLayout对象,可以设置列参数cols为0,同样;如果要创建一个列数固定的GridLayout对象,可以设置行参数rows为0。

【例10-2】一个GridLayout管理器的简单应用示例。

import java.awt.*;

public class MyGridLayout

{

      public static void main(String args[])

      {

        Frame f = new Frame("GridLayout");

        f.setLayout(new GridLayout(3,2));

        f.add(new Button("1")); //第一行第一列

        f.add(new Button("2")); //第一行第二列

        f.add(new Button("3")); //第二行第一列

        f.add(new Button("4")); //第二行第二列

        f.add(new Button("5")); //第三行第一列

        f.add(new Button("6")); //第三行第二列

        f.addWindowListener(new CloseFrame()); //closeFrame类参见例10-6

图10-5  网格布局

 

        f.setSize(200,200);

        f.setVisible(true);

      }

}

运行结果如图10-5所示。

3.边界布局(BorderLayout)

BorderLayout管理器是Window、Frame和Dialog的默认布局管理器。BorderLayout管理器把容器分成5个区域:North、South、East、West和Center,每个区域只能放置一个组件。

BorderLayout 类提供的构造方法主要有两个。

·    public BorderLayout( ):创建水平和垂直间距都为零的BorderLayout 对象。

·    public BorderLayout(int hgap, int vgap):以指定的水平和垂直间距来创建BorderLayout对象。

【例10-3】本例中的MyBorderLayout 类演示了水平和垂直间距都为零时的布局管理效果。程序文件名为MyBorderLayout.java。

import java.awt.*;

 class MyBorderLayout

{

public static void main(String args[])

      {

        Frame f = new Frame("BorderLayout");

        f.setLayout(new BorderLayout()); //设置窗体容器的布局管理器

        //在不同方位加入不同的按钮

图10-6  边界布局

 

        f.add("North", new Button("北"));

        f.add("South", new Button("南"));

        f.add("East", new Button("东"));

        f.add("West", new Button("西"));

        f.add("Center", new Button("中间"));

        f.addWindowListener(new CloseFrame());

        f.setSize(200,200);

        f.setVisible(true);

      }

}

运行结果如图10-6所示。

4.卡片布局(CardLayout)

CardLayout管理器把容器分成许多层,每层的显示空间占据整个容器的大小,但是每层只允许放置一个组件。当然每层都可以利用Panel 来实现复杂的用户界面,形成同一显示空间上的多层显示的效果。可以想像共享成员之间就像扑克牌一样摞在一起,只有最上面的成员是可见的,CardLayout管理器处理这些成员时就像在换牌:可以定义每张牌的名字,通过牌的名字来选择;也可以顺着牌序向前或向后翻牌;或者直接选择第一张或者最后一张。

CardLayout类提供了两个构造方法来创建CardLayout对象。

·    public CardLayout( ):创建一个间距为0的CardLayout对象。

·    public CardLayout(int hgap, int vgap):以指定的间距创建一个CardLayout对象。

CardLayout类也提供了一些常用的方法来管理布局和组件,如表10-5所示。

表10-5  CardLayout类中常用的方法

方   法

说   明

public int getHgap()

获取水平间距

public int getVgap()

获取垂直间距

public void first(Container parent)

指定当前组件为第一个加入的组件

public void next(Container parent)

指定当前组件为下一个加入的组件

续上表

方   法

说   明

public void previous(Container parent)

指定当前组件为上一个加入的组件

public void last(Container parent)

指定当前组件为最后一个加入的组件

public void setHgap(int hgap)

重置水平间距

public void setVgap(int vgap)

重置垂直间距

【例10-4】本例的MycardLayout.java程序采用两个面板,一个面板以FlowLayout管理器来管理按钮,另一个则以CardLayout管理器管理20个画布组件,根据按钮来显示不同的画布组件,窗体则以BorderLayout管理器来管理两个面板组件。

import java.awt.*;

import java.awt.event.*;

 class MyCardLayout implements ActionListener

{

static CardLayout myCard=new CardLayout(); //创建布局管理器

static Panel p1=new Panel();

public static void main(String args[])

{

            int i;

            MyCanvas my[]=new MyCanvas[21]; //创建数据元素为MyCanvas对象的数组

            p1.setLayout(myCard);             //设置CardLayout管理器

            for(i=1;i<=20;i++)

            {

                   my[i]=new MyCanvas(i,i);      //创建一个画布,半径为i,i

                   p1.add("i am"+i,my[i]);

            }

        Panel p2=new Panel();

             p2.setLayout(new FlowLayout()); //设置流式布局管理器

             Button b1=new Button("第一张");

             Button b2=new Button("下一张");

             Button b3=new Button("最后一张");

             p2.add(b1);

            p2.add(b2);

             p2.add(b3);

             //对各个按钮注册监听器

             b1.addActionListener(new MyCardLayout());

             b2.addActionListener(new MyCardLayout());

             b3.addActionListener(new MyCardLayout());

             Frame f=new Frame("请看我的画图效果!");

             f.setLayout(new BorderLayout());

             f.add(p1,"Center");

             f.add(p2,"South");

             f.setBounds(0,0,260,200);

             f.addWindowListener(new CloseFrame()); //closeFrame类参见例10-6

             f.setVisible(true);

     }

     public void actionPerformed(ActionEvent e)

     {

         if (e.getActionCommand()=="第一张")

             myCard.first(p1); //显示第一张

         if (e.getActionCommand()=="下一张")

             myCard.next(p1); //显示下一张

             if (e.getActionCommand()=="最后一张")

             myCard.last(p1); //显示最后一张

     }

}

     // 类MyCanvas设计:在画布上画一个圆

    

class MyCanvas extends Canvas

{

         int x,y; //椭圆的纵横半径

         MyCanvas(int x,int y) //确定大小参数以及画布的大小

         {

            this.x=x;

            this.y=y;

            this.getSize();

         }

         public void paint(Graphics g) //重绘信息

         {

            g.setColor(Color.red); //设置颜色

            g.drawString("我是第"+x,20,20); //绘制字符串信息

            g.fillOval(50,50,4*x,4*y); //填充圆

         }

         public Dimension getPreferredSize()

         {

            return new Dimension(200,200);

         }

}

该程序的运行结果如图10-7所示。

图10-7  卡片布局