您的位置: 网站首页 > 程序开发 > 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管理器是PanelApplet 的默认布局管理器。其组件的放置规律是从上到下、从左到右,如果容器足够宽,第一个组件先添加到容器中第一行的最左边,后续的组件依次添加到上一个组件的右边,如果当前行已放置不下该组件,则放置到下一行的最左边。

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-43个按钮都处于同一行,如果把该窗口变窄,窄到刚好只能够放下一个按钮,则第二个按钮将折到第二行,第三个按钮将折到第三行。

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对象,可以设置列参数cols0,同样;如果要创建一个列数固定的GridLayout对象,可以设置行参数rows0

【例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管理器是WindowFrameDialog的默认布局管理器。BorderLayout管理器把容器分成5个区域:NorthSouthEastWestCenter,每个区域只能放置一个组件。

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( )创建一个间距为0CardLayout对象。

·    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  卡片布局