默然说话

一个异想天开的人做着异想天开的梦

牟勇ID:mouyong
64549次访问,排名1577好友4人,关注者6
我快乐,我存在
mouyong的文章
原创 108 篇
翻译 4 篇
转载 30 篇
评论 12 篇
默然的公告
如果要联系我,希望能说明来意,谢谢.

点击这里给我发消息

Google

最近评论
peigen:又~~~~为什么是又呢???
dcopperfield:顶下
gaoyunpeng:无意中进入到这个博客,很快就被里面的内容所吸引,感觉很有意思,不知道为什么会有这样的感觉,或许只是一种直觉上的吸引吧,一直在看博客里的文章,觉得很不错,天天等更新,哈哈,终于看到新的文章啦~
我会一直关注的~
mouyong:谢谢你的鼓励,我会更加努力。
了祝愿你实现自己的理想,达成自己的目标
wsspy007:牟老师,我发现你是我见过最好的老师了,为学生考虑最多,一切为学生着想,不知道牟老师还记得我么,张伟(无名小辈肯定你是忘记了),第一期跟杨大宇他们在一个班的,补考两次都没有及格,我现在不在昆明了,在胜利油田,这里一切都很好,一个月的薪金能顶得上昆明3-5个月的薪水,但是我不喜欢这份工作,钱固然多,但是从学校出来步入社会以后才发现,我还是应该走软件开发这条路,现在每天我只睡4-6个小时,工作12……
文章分类
收藏
    相册
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 Java2游戏编程读书笔记(5-1)收藏

    新一篇: Java2游戏编程读书笔记(5-2) | 旧一篇: Java2游戏编程读书笔记第四章参考答案

     
    并不是我反应迟钝,只是我接到的是完全无用的指令。
    ——卡尔文,《卡尔文和霍布斯》
    发布游戏有很多方法。我们已经知道,Java应用程序可以在任何支持Java的环境中运行。这些环境不仅包括Solaris和Windows,而且还包括手持设备和“智能”设备,甚至可以在搅拌机上编写游戏。然而,运行游戏最流行的方法还是从Web浏览器或者Sun的appletviewer工具运行Applet。在本篇开头,我们将研究一下Java的Applet类,并且研究一下怎样用很少的代码来开发可视化的程序。
    到目前为止,我们应该已经具备了很多制作游戏必不可少的知识。已经掌握了Java语言的基本知识并且已经知道恰当地使用现成的Java类。在本篇中,我们将开始进行关于Java2-D游戏编程的研究。基于此目的,我们将探讨一下Java抽象Window工具包(AWT),及其主要扩展:Java 2-D,特别是以下主题:
    q        Applet基础:Applet究竟是什么,以及applet的结构和用途
    q        AWT组件:包括使用按钮,下拉列表框,文本框和布局管理器来提供和用户的交互。
    q        事件处理:包括怎样捕获鼠标和键盘事件并且正确响应这些事件。
    q        Java 2-D:通过两章来纵览图形的建模,着色和填充,从文件加载和绘制图像,到文本的操作和着色。还将讨论几何叠加,冲突测试和图像增强之类的主题。
    现在翻到第5章——Applet基础,准备学习如何创建一个交互的可视应用程序框架来构建Java游戏。
    在本章,我们将研究applet的构成组件,看看applet和application之间有什么不同,并给出几个applet例子。由于本书的主要部分集中在基于applet的游戏开发上,因此首先搞清楚applet的工作机制是大有裨益的。
    我们还将研究怎样把AWT组件添加到applet上。Java AWT包括一系列用来绘制可视化组件的类和接口。它们的根是Component类。在java.awt包中。
    Component类是一个抽象类,用来扩展以创建特定的控件。所有的AWT类,包括容器类,都从Component类扩展而来。下面描述了Component类及其子类的层次关系。注意,这幅图并没有描述所有的AWT类,它只是描述了Component的扩展关系。
    ――――――――Component
                                          
    |—Button                          |-Container
    |-Canvas                                       |-Panel
    |-Checkbox                                          |-Applet
    |-Label                                                 |-Window
    |-List                                                                 |-Dialog
    |-Scrollbar                                                             |-FileDialog
    |-TextComponent                                                |-Frame
                  |-TextArea
                  |-TextField
    简单地说,一个Java applet就是一个嵌入在另一个程序里面运行的应用程序。换句话说,applet是不能独立运行的应用程序。
     
    5.2      Applet和Application的比较
    application是能独立于除Java虚拟机之外的所有软件运行。
    5.3      Applet的组成和生命周期
    Java Applet类中包含了初始化和运行applet所需要的方法,所需要做的工作是根据需要利用继承机制来覆盖Applet类的这些方法。当applet被加载到applet运行环境时,一些方法按照特定的顺序依次被调用。在Applet类范围内,这些方法事实上并不做任何事情。不过,它们并没有被声明为abstract,所以并不是非得覆盖它们。尽管如此,它们只是作为框架以供applet遵循。
    当一个applet被加载到它的运行环境中时,它的init方法被调用。在init方法中,应该提供对applet进行初始化的代码,这包括初始化游戏中的对象以及加载游戏可能用到的图像和声音。接着被调用的方法是start,它只是传达applet已经作好执行的准备。可以使用start方法做诸如开始动画系列和线程之类的事情。
    在start方法完成之后,paint方法被调用。在这里,applet的可视化内容被提供给窗体。而这个部分将会是我们的重点,因为用户会看到什么,将都在这个方法中被绘制。
    stop方法是在Web浏览器被关闭或用户切换到其它网页的时候会被调用的方法,它结束applet的执行。所以如果在start方法中启动了动画,那么可以在这里结束它。在applet中最后被调用的是destroy方法,在这里可以中止活动着的对象,比如在applet的生命周期中所创建的线程。
    下面的程序ManyShaps继承了Applet类并且只定义了一个方法:paint方法。这个paint方法在窗体上绘制10000幅图形。在每一次循环中,根据一个随机数选择所要绘制的图形。
    import java.applet.*;
    import java.awt.*;
    import java.util.*;
     
    public class ManyShapes extends Applet{
           //覆盖Applet类的paint方法
           public void paint(Graphics g){//用来绘制的图形环境
                  Random r=new Random();
                 
                  for(int i=0;i<10000;i++){
                         //设置随机坐标
                         int x=r.nextInt()%300;
                         int y=r.nextInt()%300;
                         //设置随机宽高
                         int width=r.nextInt()%300;
                         int height=r.nextInt()%300;
                        
                         //设置随机颜色
                         g.setColor(new Color(r.nextInt()));
                        
                         //产生一个在0与4之间的正数,以确定画什么样的图形
                         int n=Math.abs(r.nextInt()%5);
                        
                         //根据n的值绘制一幅图形
                         switch(n){
                                case 0:
                                       g.draw3DRect(x,y,width,height,true);
                                       break;
                                case 1:
                                       g.drawRect(x,y,width,height);
                                       break;
                                case 2:
                                       g.drawOval(x,y,width,height);
                                       break;
                                case 3:
                                       g.fillRect(x,y,width,height);
                                       break;
                                case 4:
                                       g.fillOval(x,y,width,height);
                                       break;
                                default:
                                       System.out.println("非法类型:"+n);
                                       break;
                         }
                  }
           }
    }
    这一次只需要为程序定义一个方法,不需要定义像init那样的方法,因为没有类成员需要初始化。试运行上面的代码。如果需要编译和运行applet,可以参看下面部分。
    现在复习一下怎么从命令行编译并运行刚完成的applet。如果还没有动手的话,请在一个命名为ManyShapes.java的文件中输入上面的程序清单。现在,必须创建一个后缀为.html的文件,在这个文件中包含一个用来装载applet的<applet>标签。下面的html代码用宽和高均为300像素的区域加载ManyShapes类。这里还在applet的前后各添加一个水平规则标签(<hr>),把它和这个文件的其他部分分隔开来。如果用户喜欢,也可以包含它。
    <html>
           <head>
                  <title>ManyShapes</title>
           </head>
     
           <body>
                  <hr>
                  <applet code=ManyShapes></applet>(原书这个地方写成了“ManyShapes.java”,个人观点:这样写不太正确,但经测试通过了,HTML真的很奇怪呀。)
                  <hr>
           </body>
    </html>
    现在可以把这个.html文件以任何文件名保存,这里以一种没什么新意的方式存为ManyShapes.html。
    现在可以编译源代码。和往常一样,如下调用javac工具
    javac ManyShapes.java
    如果出现什么错误请修正后再编译。一旦完成了编译,可以很简单地用自己喜欢的(支持java的)Web浏览器打开那个html文件,或者用appletviewer工具来打开它:
    appletviewer ManyShapes.html
    恭喜你!你的第一个Java applet——ManyShapes applet运行起来了。
    5.6      通用AWT组件
    为了加强印象,下面列出在applet中添加AWT组件的几个必需步骤:
    q        在applet类中实现EventListener接口。
    q        定义实现EventListener接口所必需的方法,可以暂时让这些方法为空。
    q        在类中添加private或者protected的类成员。
    q        初始化AWT组件、注册并把新创建的AWT组件添加到容器中。
    q        填充EventListener接口的那些方法。
    关于EventListener接口,个人觉得其实使用匿名类的形式也许会更好。另外,请大家要注意的是:这里说的EventListener接口,指的是所有XXXXXXListener接口,而不仅仅只是说EventListener接口,后面将要提到的ActionListener也是一个EventListener(即ActionListener继承自EventListener)。
    5.6.1         按钮
    import java.applet.*;
    import java.awt.*;
    import java.awt.event.*;
     
    public class ButtonTest extends Applet implements ActionListener{
           private Button button;//按钮
          
           //背景色
           private final Color[] bgColors={Color.RED,Color.BLUE,Color.GREEN,Color.YELLOW};
          
           //当前背景色索引
           private int currentColor;
          
           //重写Applet类的init()方法
           public void init(){
                  button=new Button("点我");//创建一个按钮对象
                  button.addActionListener(this);//注册监听
                  this.add(button);//添加按钮到applet中
                 
                  //初始化背景色的索引
                  currentColor=-1;
                  changeWindowColor();
           }
          
           public void paint(Graphics g){
                  //根据当前的索引设置窗体的背景色
                  setBackground(bgColors[currentColor]);
                  //设置按钮文本色为窗体背景色
                  button.setForeground(bgColors[currentColor]);
           }
          
           //当前索引递增
           public void changeWindowColor(){
                  currentColor++;
                  if(currentColor==bgColors.length){
                         currentColor=0;
                  }
           }
          
           public void actionPerformed(ActionEvent e){
                  //如果按钮产生事件,改变窗口的背景色
                  if(button==e.getSource()){
                         changeWindowColor();
                         repaint();
                  }
           }    
    }
    这个Applet类为了把自己注册为一个可以接收按钮事件的对象而实现了ActionListener接口。ActionListener接口只定义了惟一的一个方法:actionPerformed,这个方法以ActionEvent对象作为参数。当一个事件发生时(比如单击并松开一个按钮),一个描述这个事件的ActionEvent对象被构建并传送给actionPerformed方法。在actionPerformed方法中可以定义实际发生的动作。
    此外,我们还应该知道ActionEvent类的getSource方法的用法,它返回的是触发该事件的对象。当有多个组件并把它们用同样的ActionListener注册时,这是很有用的。
    5.6.2         复选按钮
    复选按钮和普通按钮不一样的地方在于:与复选按钮的交互不能被ActionListener捕获。取而代之的是,applet必须实现ItemListener接口。ItemListener接口和ActionListener很相似,它也只定义了一个方法:itemStateChanged,这个方法以ItemEvent作为参数。
    使用单选按钮都需要把复选按钮放入按钮组中(是的,Java AWT中的复选框和单选按钮是同一个控件的两种表现形式)。按钮组保证在组内只有一个单一的选择。当组内的一个成员被选中时,组内其他的所有成员都被自动设为非选中。当applet要求一组成员中只有一个可以激活时,可以这样做。在Java中,CheckboxGroup类用来装载一组单选按钮。
    import java.applet.*;
    import java.awt.*;
    import java.awt.event.*;
     
    public class CheckboxTest extends Applet implements ItemListener{
           //用来容纳几个单选框的CheckboxGroup
           private CheckboxGroup cbg;
          
           //applet采用的选项
           private final String[] selections={"百事可乐","可乐","私酿威士忌","Tab"};
          
           private Checkbox createCheckbox(
                         String label,                  //复选按钮标签
                         CheckboxGroup group, //所属的组
                         boolean enabled                    //为真则设置这个复选框选中
                  )
           {
                  Checkbox cb=new Checkbox(label,group,enabled);
                  cb.addItemListener(this);
                  return cb;
           }
          
           //重写Applet类的init方法
           public void init(){
                  cbg=new CheckboxGroup();
                  for(int i=0;i<selections.length;i++){
                         this.add(createCheckbox(selections[i],cbg,false));
                  }
           }
          
           public void itemStateChanged(ItemEvent e){
                  //打印一条选择信息
                  System.out.println("是的,我也同意,"+cbg.getSelectedCheckbox().getLabel()+"非常好喝!");
                 
           }
    }
    5.6.3         作出重要选择
    另外一个可能很有用的组件是Choice类,它使用起来很简单。Windows下的程序员知道它就是ComboBox,而Choice以类似的方式给用户提供了一个供选择的下拉列表框。里面的选项以String对象的方式来维护。
    和Checkbox相类似,Choice对象向ItemListener类注册监听,ItemListener类必须实现ItemStateChanged方法,。
    import java.applet.*;
    import java.awt.*;
    import java.awt.event.*;
     
    public class ChoiceTest extends Applet implements ItemListener{
           //我们骨骼的技术名字
           public final String[] BONES={"脚","腿","膝","臀","肋","肩","颈"};
          
           private Choice choice;
          
           public void init(){
                  this.setBackground(new Color(125,0,125));
                 
                  //创建Choice并注册监听
                  choice=new Choice();
                 
                  for(int i=0;i<BONES.length;i++){
                         //添加一个字符串来描述每一种选择
                         choice.add(BONES[i]);
                  }
                  choice.addItemListener(this);
                  this.add(choice);
           }
          
           //在已注册的监听器改变时调用
           public void itemStateChanged(ItemEvent e){
                  //产生一个与当前所选的项不同的索引
                  int index;
                  do
                  {
                         index=(int)(Math.random()*BONES.length);
                  }while(index==choice.getSelectedIndex());
                 
                  System.out.println(choice.getSelectedItem()+"骨连接了"+BONES[index]+"骨....");
           }
    }
    5.6.4         循环播放声音文件
    虽然用Java applet播放声音是一件微不足道的事情,但这里还是要谈几点。首先,建议所有声音文件采用Sun的.au格式,它可又保证跨平台工作。虽然其他的格式可能在Windows下工作正常,但是在Linux或者Mac之类的系统中则可能失效。
    现在,让我们关注一下在applet中加载声音文件的最直接的方式。类Applet提供了集中加载并播放声音的方法。有两种直接播放声音的方法,都又play命名,其中之一用一个URL对象和一个String对象作为输入,另一个只又一个URL对象作为输入。这两种方法创建一个临时的AudioClip对象,然后马上把它的数据以流的方式输出为声音。即使声音文件不存在或者不可用,也并不会产生错误。
    因为空闲时也在不断读和播放数据,所又play方法浪费内存并且有潜在使applet运行变慢的可能。处理游戏更好一点的方法是提前缓冲声音数据。在这种方式中,如果一个声音需要一次次重复播放的话,可又把它先加载到内在中的一个地方,又后只需从这个地方读取。Java提供了AudioClip这个接口来播放,循环,停止声音。虽然AudioClip是一个接口,但是Java在各个平台的各个版本都定义了它们自己内部的AudioClip的实现类。由于只是进行一般意义的编程,所以需要考虑的只是这个范围内的AudioClip。
    要创建一个AudioClip对象,可又使用Applet类的getAudioClip方法。这个方法和play方法很类似,也是以一个URL对象或者一个URL对象和一个String对象作为输入。当声音内容和applet字节码储存在同一个位置时,建议使用两个参数的形式。
    比如下面的代码加载一个名为bang.au的文件:
    AudioClip ac=getAudioClip(getCodeBase(),”bang.au”);
    getCodeBase方法返回applet字节码所处的位置,所又不管是在远程还是在本地运行这个applet,上面的调用方法都可又正常工作。
    第三种加载音频片段的方法是使用Applet类的newAudioClip方法。这个方法只有一种形式,又一个指向声音文件的URL对象作为输入。由于它是一个static的方法,当想加载一个声音却又没有一个指向可用的applet对象的引用时,这是很有用的。
    import java.applet.*;
    import java.awt.*;
    import java.awt.event.*;
     
    public class AudioChoiceTest extends Applet implements ActionListener{
           //程序中声音的名字
           public final String[] AUDIO={"ping","pop","return","salvation","shuffle","squish"};
          
           //包含上述字符串数组的下拉列表框
           private Choice choice;
          
           //真实的音频片段数据
           private AudioClip[] clips;
          
           //控制播放和停止的按钮
           private Button playClip;
           private Button loopClip;
           private Button stopClip;
           private Button stopAllClips;
          
           //跟踪当前哪些音频片段在播放
           private boolean[] clipsPlaying;
          
           public void init(){
                  this.setBackground(new Color(48,255,0));
                 
                  //构建下拉列表框和AudioClip对象
                  choice=new Choice();
                  clips=new AudioClip[AUDIO.length];
                  clipsPlaying=new boolean[AUDIO.length];
                  for(int i=0;i<AUDIO.length;i++){
                         //为每一个选项添加一个描述的字符串
                         choice.add(AUDIO[i]);
                         //添加音频片段的路径和扩展名
                         clips[i]=this.getAudioClip(getCodeBase(),"audio/"+AUDIO[i]+".au");
                         System.out.println(getCodeBase()+"audio/"+AUDIO[i]+".au");
                         //标志这个片段是否在播放的布尔值
                         clipsPlaying[i]=false;
                  }
                  this.add(choice);
                 
                  //创建播放和停止按钮
                  playClip=new Button("播放");
                  playClip.addActionListener(this);
                  this.add(playClip);
                 
                  loopClip=new Button("循环");
                  loopClip.addActionListener(this);
                  this.add(loopClip);
                 
                  stopClip=new Button("停止");
                  stopClip.addActionListener(this);
                  this.add(stopClip);
                 
                  stopAllClips=new Button("全部停止");
                  stopAllClips.addActionListener(this);
                  this.add(stopAllClips);
                 
                  //如果没有什么要停止的话,把"停止"按钮变灰
                  stopClip.setEnabled(false);
                  stopAllClips.setEnabled(false);
           }
          
           //停止所有音频片段的播放
           public void stop(){
                  for(int i=0;i<AUDIO.length;i++){
                         if(clipsPlaying[i]){
                                clips[i].stop();
                         }
                  }
           }
          
           //允许用户使音频片段播放,循环播放或者停止
           public void actionPerformed(ActionEvent e){
                  int clipIndex=choice.getSelectedIndex();
                  System.out.println(clipIndex);
                  AudioClip clip=clips[clipIndex];
                 
                  //播放被选中的音频片段
                  if(e.getSource()==playClip){
                         clip.play();
                         stopClip.setEnabled(true);
                         stopAllClips.setEnabled(true);
                         clipsPlaying[clipIndex]=true;
                  }else if(e.getSource()==stopClip){//循环播放被选中的音频片段
                         clip.stop();
                         stopClip.setEnabled(false);
                         stopAllClips.setEnabled(false);
                        
                         clipsPlaying[clipIndex]=false;
                        
                         //只要有一个音频片段在播放就激活"停止"按钮
                         for(int i=0;i<AUDIO.length;i++){
                                if(clipsPlaying[i]){
                                       stopClip.setEnabled(true);
                                       stopAllClips.setEnabled(true);
                                       break;
                                }
                         }
                  }else if(e.getSource()==stopAllClips){
                         for(int i=0;i<AUDIO.length;i++){
                                if(clipsPlaying[i]){
                                       clips[i].stop();
                                       clipsPlaying[i]=false;
                                }
                         }
                        
                         stopClip.setEnabled(false);
                         stopAllClips.setEnabled(false);
                  }else if(e.getSource()==loopClip){
                         clip.loop();
                         stopClip.setEnabled(true);
                         stopAllClips.setEnabled(true);
                         clipsPlaying[clipIndex]=true;
                  }
                 
           }
    }
    //这个声音播放的程序让我感觉到play()方法似乎有一点问题,因为在用play()进行播放时
    //如果声音播放时间很短的时候,会听不到声音的播放,而loop()却没有这个问题。
    //会不会是Windows下面才有这个问题呢?很值得思考。
    Java允许几个声音同时播放(因为每一个AudioClip就是一个线程嘛,这是很符合逻辑的),产生所有声音播放流的混合物,这使得不太费力就可以产生一些美妙的效果。
    注意:如果想提供一个让用户能够从同一组中作出多项选择的界面,可以考虑使用List对象。可以查阅Java 2文档,了解更多关于List类的内容。
    注意:不仅可以对对象添加监听器,而且还可以删除监听器。Button类有一个用来删除事件监听器的removeActionListener()方法。当applet的stop方法被调用时,删除监听器的方法也会调用。然而,由于一旦父线程被清除,所有的子线程也会被清除,所以当applet停止时并没有必要删除监听器。
    5.6.5         文本域(TextField)
    5.6.6         标签
    5.7      布局管理
    Java使用布局管理器来控制组件的摆放,实现LayoutManager接口的类知道如何在窗口内放置组件。在Java.awt包中有几个实现了LayoutManager接口的类,下面从FlowLayout类开始学习。
    5.7.1         FlowLayout类
    FlowLayout类可能是java.awt布局类中最简单的一个,它简单的按照组件被添加到applet的顺序从左到右摆放组件。这是默认的布局管理器。
    如果想直接指定使用FlowLayout类(或其他的布局管理器),一般需要在容器的init方法中调用setLayout()方法。
    setLayout(new FlowLayout());
    FlowLayout类除了默认构造函数外,还有两个构造函数。第一个以一个描述布局对齐方式的init值作为输入参数,这个参数可以取5个值:LEFT CENTER RIGHT LEADING和TRAILING。下面的代码创建一个左对齐,水平和垂直间距都为10的FlowLayout:
    setLayout(new FlowLayotu(FlowLayout.LEFT,10,10));
    如果构造函数时没有输入参数,则默认的对齐方式为FlowLayout.CENTER,默认的间距为5像素。
    5.7.2         GridLayout类
    GirdLayout把组件放在一定行数和列数的网格中,网格中所有的组件尺寸都相同。
    创建一个GridLayout类的方式和创建FlowLayout类似,只是它有不同的构造函数。默认函数每列放置一个组件,其他两个构造函数如下所示:
    GridLayout(int rows,int cols);
    GridLayout(int rows,int cols,int hgap,int vgap);
    第一个指定了多行多列的网格,可以放置rows*cols个组件,第二个还指定了水平和垂直间隔(第三个和第四个参数)。如果不指定间隔,它们就默认为零,如果把行数或者列数指定为零,或者添加比行数乘列数还多的组件,这个布局管理器将调整其属性值使得组件仍然在它的网格之中。
    import java.applet.*;
    import java.awt.*;
    import java.util.*;
     
    public class GridLayoutTest extends Applet{
           public void init(){
                  //创建一个字符串和一个解析字符串的StringTokenizer
                  String string="My Head Is My Only House Unless It Rains";
                  StringTokenizer st=new StringTokenizer(string);
                 
                  //创建一个3×3的网格布局,组件之间的间隙为5像素
                  setLayout(new GridLayout(3,3,5,5));
                 
                  //为每一个标志字符串创建一个背景为绿色的标签并把它加到panel上
                  while(st.hasMoreTokens()){
                         Label label=new Label(st.nextToken(),Label.CENTER);
                         label.setBackground(Color.green);
                         this.add(label);
                  }
           }
    }
    1.7.3         BorderLayout类
    BorderLayout类是另外一种布局管理器。这个类按照4个方向(北,南,东,西)的顺序排列组件,还定义了第五个方位:中。
    setLayout(new BorderLayout());
     
    add(new Button("North"),BorderLayout.NORTH);
    add(new Button("South"),BorderLayout.SOUTH);
    add(new Button("East"),BorderLayout.EAST);
    add(new Button("West"),BorderLayout.WEST);
    add(new Button("Center"),BorderLayout.CENTER);
     
    除了默认构造函数外,还有一个构造函数,以分隔组件的水平和垂直间距为输入参数。
    1.7.4         CardLayout类
    CardLayout类把组件像一叠卡片那样一个叠一个地放在一起。CardLayout类有两个构造函数:默认构造函数和一个以水平和垂直间距为输入参数的构造函数。
    下面的applet以动画的形式切换标着“Card 1”~“Card 10”的10个按钮对象,每一秒钟显现队列中的一个按钮。
    import java.applet.*;
    import java.awt.*;
     
    public class CardTest extends Applet implements Runnable{
           //一个充当定时器的线程
           private Thread timer;
          
           public void init(){
                  //创建一个新的CardLayout
                  setLayout(new CardLayout());
                 
                  //在CardLayout中创建10个按钮
                  for(int i=1;i<=10;i++){
                         //第二个参数是卡片面板的名字
                         add(new Button("Card"+i),"Card"+i);
                  }
                 
                  //把这个applet注册为Thread
                  timer=new Thread(this);
           }
          
           public void start(){
                  timer.start();
           }
          
           public void stop(){
                  timer=null;
           }
          
           //重写Runnable接口的run方法
           public void run(){
                  //获得当前的布局管理器
                  CardLayout layout=(CardLayout)this.getLayout();
                 
                  //得到这个线程的一个引用
                  Thread t=Thread.currentThread();
                 
                  //当线程active时循环
                  while(t==timer){
                         layout.next(this);
                        
                         //在更新前等待1秒
                         try{
                                timer.sleep(1000);
                         }catch(InterruptedException e){
                                return;
                         }
                  }
           }
    }
    CardLayout类还有一些值得注意的方法,其中,first和last方法分别显示布局中的第一个和最后一个,还有一个显示布局中先前组件的previous方法。它们都是以一个Container对象作为输入参数。在这里,它是applet本身。
    CardLayout类值得关注的第五个方法就是show方法,它以一个Container对象作为它的第一个参数,以一个String对象作为第二个参数,其中的String对象必须和创建布局时的add方法的第二个参数(也是一个String)对应。比如,下面的代码就可以显示标有“Card5”的按钮。
    layout.show(this,"Card 5");
     

    发表于 @ 2006年12月30日 23:25:00|评论(loading...)|编辑

    新一篇: Java2游戏编程读书笔记(5-2) | 旧一篇: Java2游戏编程读书笔记第四章参考答案

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © 默然