现在的位置: 首页 > 综合 > 正文

java,applet 容器、组件和布局管理器

2013年10月22日 ⁄ 综合 ⁄ 共 12817字 ⁄ 字号 评论关闭

10.2.1 容器
  AWT容器分为两类:外部容器和内部容器。其中,外部容器一般会独立存在,例如Frame类;而内部容器则会嵌套在外部容器内部使用,例如Panel类。容器的层次结构如图10-2所示。

  
  
  图10-2 AWT容器的层次结构
  其中两个最常用的容器是Frame和Panel。在后面我们还要单独介绍Applet(一种特殊的Panel)。
  框架(Frame):Frame是顶级窗口,可以显示标题,重置大小。
  面板(Panel):面板提供了建立应用程序的空间。我们可以把图形元件(包括其他面板)放在一个面板上,然后把这个面板作为内部容器放在Frame等外部容器上。
  容器类的常用方法包括:
  add()
  add(Component com)
  add(Component, int index)
  add(Component component, Object constraints)
  add(String name, Component component),
  add(Component component, Object constraints, int index)
  setLayout() and getLayout()
  getComponent()
  getInsets()
  remove and removeAll()
  validate()
  这些方法主要与我们后面讲的步骤,例如布局管理、添加组件有关。
  10.2.2 布局管理
  选择了容器之后,可以通过容器的setLayout()和getLayout()方法来确定布局(Layout),也就是限制容器中各个组件的位置和大小等。
  Java提供了多种布局,如顺序布局(Flow Layout)、边界布局(Border Layout)和网格布局(Grid Layout)等。
  1.顺序布局
  顺序布局(Flow Layout)是最基本的一种布局,面板的默认布局就是顺序布局。顺序布局指的是把图形元件一个接一个地放在面板上。下面是一个顺序布局的例子。
  package sample;
  import java.awt.*;
  import java.awt.event.WindowAdapter;
  import java.awt.event.WindowEvent;
  public class MyFlowLayout {
  private Frame f;
  private Button button1, button2, button3;
  
  public static void main (String args[]) {
  MyFlowLayout mflow = new MyFlowLayout ();
  mflow.go();
  }
  
  public void go() {
  f = new Frame ("FlowLayout演示");
  f.addWindowListener(new WindowAdapter(){
  public void windowClosing(WindowEvent evt) {
  f.setVisible(false);
  f.dispose();
  System.exit(0);
  }
  });
  //f.setLayout(new FlowLayout());
  f.setLayout(new FlowLayout(FlowLayout.LEADING, 20, 20));
  button1 = new Button("确定");
  button2 = new Button("打开");
  button3 = new Button("关闭");
  f.add(button1);
  f.add(button2);
  f.add(button3);
  f.setSize (200,200);
  f.pack();
  f.setVisible(true);
  }
  }
  程序运行结果见图10-3。
  
  
  图10-3 顺序布局(Flow Layout)
  2.边界布局
  边界布局(Border Layout)包括5个区:北区、南区、东区、西区和中区。这5个区在面板上的分布规律是“上北下南,左西右东”。下面是一个边界布局的例子。

  package sample;
  import java.awt.*;
  import java.awt.event.WindowAdapter;
  import java.awt.event.WindowEvent;
  public class MyBorderLayout {
  Frame f;
  Button east, south, west, north, center;
  
  public static void main(String args[]) {
  MyBorderLayout mb = new MyBorderLayout();
  mb.go();
  }
  
  public void go() {
  f = new Frame("BorderLayout 演示");
  f.addWindowListener(new WindowAdapter(){
  public void windowClosing(WindowEvent evt) {
  f.setVisible(false);
  f.dispose();
  System.exit(0);
  }
  });
  
  f.setBounds(0,0, 300, 300);
  f.setLayout(new BorderLayout());
  
  north = new Button("北");
  south = new Button("南");
  east = new Button("东");
  west = new Button("西");
  center= new Button("中");
  
  f.add(BorderLayout.NORTH, north);
  f.add(BorderLayout.SOUTH, south);
  f.add(BorderLayout.EAST, east);
  f.add(BorderLayout.WEST, west);
  f.add(BorderLayout.CENTER, center);
  
  f.setVisible(true);
  }
  }
  程序运行结果见图10-4。
  
  
  图10-4 边界布局(Border Layout)
  3.网格布局
  网格布局(Grid Layout)把面板分成一个个大小相等的网格,你可以给出网格的行数和列数。下面是一个网格布局的例子。
  package sample;
  import java.awt.*;
  import java.awt.event.*;
  public class MyGridLayout {
  private Frame f;
  private Button[] btn;
  public static void main(String args[]) {
  MyGridLayout grid = new MyGridLayout();
  grid.go();
  }
  public void go() {
  f = new Frame("GridLayout演示");
  f.addWindowListener(new WindowAdapter(){
  public void windowClosing(WindowEvent evt) {
  f.setVisible(false);
  f.dispose();
  System.exit(0);
  }
  });
  
  f.setLayout (new GridLayout (3, 3, 10, 10));
  btn = new Button[9];
  for(int i = 0; i <=8; i++) {
  int j = i + 1;
  btn[i] = new Button("" + j);
  f.add(btn[i]);
  }
  
  // f.pack();
  f.setSize(100, 100);
  f.setVisible(true);
  }
  }
  程序运行结果见图10-5。
  
  
  图10-5 网格布局(Grid Layout)
  4.卡片布局
  卡片布局(Card Layout)把每个组件看作一张卡片,好像一副扑克牌,它们叠在一起,每次只有最外面的一个组件可以被看到。
  package sample;
  import java.awt.*;
  import java.awt.event.*;
  public class MyCardLayout {
  public static void main(String args[]) {
  new MyCardLayout().go();
  }
  
  public void go() {
  final Frame f = new Frame("CardLayout演示");
  f.addWindowListener(new WindowAdapter(){
  public void windowClosing(WindowEvent evt) {
  f.setVisible(false);
  f.dispose();
  System.exit(0);
  }
  });
  
  f.setSize(300, 100);
  f.setLayout(new CardLayout());
  
  final Frame f1 = f;
  for(int i = 1; i <= 5; ++i) {
  Button b = new Button("Button "+ i);
  b.setSize(100, 25);
  b.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent ae) {
  CardLayout cl = (CardLayout)f1.getLayout();
  cl.next(f1);
  }
  } );
  f.add(b, "button" + i);
  }
  f.setVisible(true);
  }
  }
  程序运行结果见图10-6。
  图10-6 卡片布局(Card Layout)
  单击按钮Button1后,显示下一个按钮Button2,依此类推。
  5.网格包布局
  网格包(GridBag)布局是基于网格布局之上的一种改进。和基本的网格布局不同的是,一个组件可以跨越一个或多个网格,这样一来增加了布局的灵活性。为了处理网格的跨越性,我们可以使用GridBagConstraints类。有兴趣的读者可以参考Java API来了解它。

  package sample;
  import java.awt.*;
  import java.util.*;
  import java.awt.event.*;
  public class MyGridBagLayout extends Panel {
  protected void makebutton(String name,
  GridBagLayout gridbag,
  GridBagConstraints c) {
  Button button = new Button(name);
  gridbag.setConstraints(button, c);
  add(button);
  }
  public void go() {
  GridBagLayout gridbag = new GridBagLayout();
  GridBagConstraints c = new GridBagConstraints();
  setFont(new Font("Helvetica", Font.PLAIN, 14));
  setLayout(gridbag);
  c.fill = GridBagConstraints.BOTH;
  c.weightx = 1.0;
  makebutton("Button001", gridbag, c);
  makebutton("Button2", gridbag, c);
  makebutton("Button3", gridbag, c);
  c.gridwidth = GridBagConstraints.REMAINDER; //end row
  makebutton("Button4", gridbag, c);
  c.weightx= 0.0; //reset to the default
  makebutton("Button5", gridbag, c); //another row
  c.gridwidth = 2; //GridBagConstraints.RELATIVE; //next-to-last in row
  makebutton("Button6", gridbag, c);
  c.gridwidth = GridBagConstraints.REMAINDER; //end row
  makebutton("Button007", gridbag, c);
  c.gridwidth =1; //reset to the default
  c.gridheight = 2;
  c.weighty = 1.0;
  makebutton("Button8", gridbag, c);
  c.weighty= 1.0; //reset to the default
  c.gridwidth = GridBagConstraints.REMAINDER; //end row
  c.gridheight = 1; //reset to the default
  makebutton("Button9", gridbag, c);
  makebutton("Button10", gridbag, c);
  setSize(300, 100);
  }
  public static void main(String args[]) {
  final Frame f = new Frame("GridBagLayout 演示");
  f.addWindowListener(new WindowAdapter(){
  public void windowClosing(WindowEvent evt) {
  f.setVisible(false);
  f.dispose();
  System.exit(0);
  }
  });
  MyGridBagLayout gb = new MyGridBagLayout();
  gb.go();
  f.add("Center", gb);
  f.pack();
  f.setVisible(true);
  }
  }
  程序运行结果见图10-7。
  
  
  图10-7 网格包(GridBag)布局
  10.2.3 AWT组件库
  本节从应用的角度进一步介绍AWT的一些组件,目的是使大家加深对AWT的理解,掌握如何用各种组件构造图形化用户界面,学会控制组件的颜色和字体等属性。在介绍组件过程中,我们提前引入了事件处理的一些相关内容(之后会详细展开)。

  下面是一些常用组件的介绍。
  1.按钮(Button)
  按钮是最常用的一个组件,其构造方法如下:
  Button b = new Button("Quit");
  当按钮被点击后,会产生ActionEvent事件,由ActionListener接口进行监听和处理事件。
  ActionEvent的对象调用getActionCommand()方法可以得到按钮的标识名,默认按钮名为label。用setActionCommand()可以为按钮设置组件标识符。

  2.标签
  标签是一种放到面板上的静止的正文。其构造方法如下:
  Label label1 = new Label("你好!")
  下面是一个标签的例子。
  import java.awt.*;
  import java.applet.Applet;
  public class LabelTest extends Applet {
  public void init() {
  setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
  Label label1 = new Label("你好!");
  Label label2 = new Label("欢迎!");
  add(label1);
  add(label2);
  }
  ……
  }
  3.复选框(Checkbox)
  复选框提供简单的“on/off”开关,旁边显示文本标签。
  其主要方法如下:
  setLayout(new GridLayout(3,1));
  add(new Checkbox("one",null,true));
  add(new Checkbox("two"));
  add(new Checkbox("three"));
  复选框用ItemListener来监听ItemEvent事件,当复选框状态改变时,用getStateChange()获取当前状态,使用getItem()获得被修改复选框的字符串对象。

  4.复选框组(CheckboxGroup)
  使用复选框组,可以实现单选框的功能,也就是说,只能选择其中的一项。方法如下:
  setLayout(new GridLayout(3, 1));
  CheckboxGroup cbg = new CheckboxGroup();
  add(new Checkbox("one", cbg, true));
  add(new Checkbox("two", cbg, false));
  add(new Checkbox("three", cbg, false));
  5.下拉式菜单(Choice)
  下拉式菜单每次只能选择其中的一项,它能够节省显示空间,适用于大量选项。
  Choice colorChooser=new Choice();
  colorChooser.add("Green");
  colorChooser.add("Red");
  colorChooser.add("Blue");
  Choice用ItemListener接口来进行监听。
  6.画布(Canvas)
  一个应用程序必须继承Canvas类才能获得有用的功能,比如创建一个自定义组件。如果想在画布上完成一些图形处理,则Canvas类中的paint()方法必须被重写。

  Canvas组件监听各种鼠标、键盘事件。当在Canvas组件中输入字符时,必须先调用requestFocus()方法。
  创建画布的实例如下:
  import java.awt.*;
  import java.applet.Applet;
  public class CanvasGUI extends Applet {
  . . .
  MyCanvas doodle;
  . . .
  public void init() {
  . . .
  //建立我们的画布
  doodle = new MyCanvas();
  doodle.reshape(0,0,100,100);
  leftPanel.add("Center",doodle);
  . . .
  }
  }
  class MyCanvas extends Canvas {
  public void paint(Graphics g) {
  g.drawRect(0, 0, 99, 99);
  g.drawString("Canvas",15,40);
  }
  }
  7.单行文本输入区(TextField)
  单行文本输入区也叫做文本域,一般用来让用户输入像姓名、信用卡号这样的信息,它是一个能够接收用户的键盘输入的小块区域。
  单行文本输入区构造方法有4种类型供选择:空的、空的并且具有指定长度、带有初始文本内容的和带有初始文本内容并具有指定长度的。下面是生成这4种文本域的代码。
  TextField tf1, tf2, tf3, tf4;
  //空的文本域
  tf1 = new TextField();
  //长度为20的空的文本域
  tf2 = new TextField(20);
  //带有初始文本内容的文本域
  tf3 = new TextField("你好");
  //带有初始文本内容并具有指定长度的文本域
  tf4 = new TextField("你好", 30);
  单行文本输入区只能显示一行,当按下回车键时,会发生ActionEvent事件,可以通过ActionListener中的actionPerformed()方法对事件进行相应处理。可以使用setEditable(boolean)方法设置为只读属性。

  8.文本输入区(TextArea)
  TextArea可以显示多行多列的文本。与文本域类似,创建文本区时也有4种类型供选择,但如果指定文本区的大小,必须同时指定行数和列数。
  TextArea ta1, ta2;
  //一个空的文本区
  ta1 = new TextArea();
  //一个带有初始内容、大小为5x40的文本区
  ta2 = new TextArea("你好!", 5, 40);
  可以用成员方法setEditable()来决定用户是否可以对文本区的内容进行编辑。
  //使文本区为只读的
  ta2.setEditable(false)
  我们可以用成员方法getText()来获得文本区的当前内容。在TextArea中可以显示水平或垂直的滚动条。要判断文本是否输入完毕,可以在TextArea旁边设置一个按钮,通过按钮点击产生的ActionEvent事件对输入的文本进行处理。

  9.列表(List)
  列表框使用户易于操作大量的选项。创建列表框的方法和下拉式菜单有些相似。列表框的所有条目都是可见的,如果选项很多,超出了列表框可见区的范围,则列表框的旁边将会有一个滚动条。列表框中提供了多个文本选项,可以浏览多项。

  List lst=new List(4,false); //两个参数分别表示显示的行数,是否允许多选
  lst.add("Venus");
  lst.add("Earth");
  lst.add("Moon");
  lst.add("Mars");
  cnt.add(lst);
  10.滚动条
  在某些程序中,需要调整线性的值,这时就需要滚动条。滚动条提供了易于操作的值的范围或区的范围。
  (1)创建滚动条
  当创建一个滚动条时,必须指定它的方向、初始值、滑块的大小、最小值和最大值。
  public Scrollbar(int orientation, int initialValue, int sizeOfSlider, int minValue, int maxValue);

  下面是一个例子。
  Scrollbar redSlider;
  public void init() {
  redSlider = new Scrollbar(Scrollbar.VERTICAL,0,1,0,255);
  add(redSlider);
  }
  (2)滚动条事件
  和其他接口元件一样,滚动条产生一个可以控制的事件;但和其他事件不同,你必须直接使用成员方法handleEvent(),而不能使用成员方法action()。
  (3)滚动条的值的显示
  如果想显示滑块所在位置的值,则需要添加一个自己的文本域。下面是一个例子。
  import java.awt.*;
  import java.applet.Applet;
  public class RedSliderTest extends Applet {
  Scrollbar redslider;
  TextField redvalue;
  Label redlabel;
  public void init( ) {
  setLayout(new GridLayout(1,3));
  redslider = new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,255);
  redvalue = new TextField("0",5);
  redvalue.setEditable(false);
  redlable = new Label("Red(0-255)");
  add(redlabel);
  add(redslider);
  add(redvalue);
  }
  public boolean handleEvent(Event e) {
  if (e.target instanceof Scrollbar) {
  redvalue.setText(Integer.toString(((Scrollbar)e.target).getValue()));
  return true;
  }
  return super.handleEvent(e);
  }
  public boolean action(Event e, Object arg) {
  System.out.println("Event"+ arg);
  return true;
  }
  }
  11.对话框(Dialog)
  对话框是Window类的子类,是一个容器类,属于特殊组件。对话框和一般窗口的区别在于它依赖于其他窗口。对话框分为非模式(non-modal)和模式(modal)两种。

  12.文件对话框(Filedialog)
  当用户想打开或存储文件时,使用文件对话框进行操作。主要代码如下:
  FileDialog d=new FileDialog(ParentFr,"FileDialog");
  d.setVisible(true);
  String filename=d.getFile();
  13.菜单(Menu)
  菜单的开发相对复杂,我们需要使用3个类:Menu、MenuBar和MenuItem。它们的层次结构如图10-8所示。
  
  
  图10-8 菜单的层次结构
  (1)MenuBar
  我们无法直接将菜单添加到容器的某一位置,也无法使用布局管理器对其加以控制。菜单只能被添加到菜单容器(MenuBar)中。MenuBar会被添加到Frame对象中,作为整个菜单树的根基。

  Frame fr = new Frame("MenuBar");
  MenuBar mb = new MenuBar();
  fr.setMenuBar(mb);
  fr.setSize(150,100);
  fr.setVisible(true);
  (2)Menu
  菜单可以被添加到MenuBar中或其他Menu中。
  Frame fr = new Frame("MenuBar");
  MenuBar mb = new MenuBar();
  fr.setMenuBar(mb);
  Menu m1 = new Menu("File");
  Menu m2 = new Menu("Edit");
  Menu m3 = new Menu("Help");
  mb.add(m1);
  mb.add(m2);
  mb.setHelpMenu(m3);
  fr.setSize(200,200);
  fr.setVisible(true);
  (3)MenuItem
  MenuItem是菜单树中的“叶子节点”。MenuItem通常被添加到一个Menu中。对于MenuItem对象可以添加ActionListener,使其能够完成相应的操作。

  Menu m1 = new Menu("File");
  MenuItem mi1 = new MenuItem("Save");
  MenuItem mi2 = new MenuItem("Load");
  MenuItem mi3 = new MenuItem("Quit");
  m1.add(mi1);
  m1.add(mi2);
  m1.addSeparator();
  m1.add(mi3);
  MenuBar和Menu都没有必要注册监听器,只需要对MenuItem添加监听器ActionListener,完成相应的操作。
  我们看一个完整的Menu实例。
  /**
  * 演示Menu、MenuBar和MenuItem的使用
  */
  package sample;
  import java.awt.*;
  import java.awt.event.*;
  class MenuTest extends Frame {
  PopupMenu pop;
  public MenuTest() {
  super("Golf Caddy");
  addWindowListener(new WindowAdapter() {
  public void windowClosing(WindowEvent evt) {
  setVisible(false);
  dispose();
  System.exit(0);
  }
  });
  this.setSize(300,300);
  //this.setLayout(new FlowLayout());
  this.add(new Label("Choose club."), BorderLayout.NORTH);
  
  Menu woods = new Menu("Woods");
  woods.add("1 W");
  woods.add("3 W");
  woods.add("5 W");
  
  Menu irons = new Menu("Irons");
  irons.add("3 iron");
  irons.add("4 iron");
  irons.add("5 iron");
  irons.add("7 iron");
  irons.add("8 iron");
  irons.add("9 iron");
  irons.addSeparator();
  irons.add("PW");
  irons.insert("6 iron", 3);
  
  MenuBar mb = new MenuBar();
  mb.add(woods);
  mb.add(irons);
  this.setMenuBar(mb);
  
  pop = new PopupMenu("Woods");
  pop.add("1 W");
  pop.add("3 W");
  pop.add("5 W");
  
  final TextArea p = new TextArea(100, 100);
  
  p.setBounds(0,0,100,200);
  p.setBackground(Color.green);
  p.add(pop);
  //以下是事件处理,稍后介绍
  p.addMouseListener(new MouseAdapter() {
  public void mouseReleased(java.awt.event.MouseEvent evt) {
  if(evt.isPopupTrigger()) {
  System.out.println("popup trigger");
  System.out.println(evt.getComponent());
  System.out.println("" + evt.getX()+ ""+ evt.getY());
  pop.show(p, evt.getX(), evt.getY());
  }
  
  }
  });
  this.add(p, BorderLayout.CENTER);
  }
  
  public static void main (String [] args) {
  new MenuTest().setVisible(true);
  }
  } 

抱歉!评论已关闭.