AsWing入门教程 1.4 在面板中显示信息

AsWing入门教程 1.4 在面板中显示信息

 

作者:胡矿

 

著作权所有,请勿转载

 

www.flashseer.org

 

Google doc

http://docs.google.com/Doc?id=dnp8gdz_63n8m3f

 

 

    本节,我们将讲述如何在框架中显示信息。我们不再像刚开始学习时那样用 trace 将字符串输出到输出面板当中,而是要把它显示在一个框架里面,如图1.4-1所示。

 

(图1.4-1)

    把信息直接输出到框架上是可能的,但是这么做被认为是不好的编程行为。在AsWing当中,框架实际上被设计为组件的容器,可以容纳菜单或者其他的用户界面元素。通常情况下,你需要在另一个组件上绘制信息,然后把它添加到框架中,这个组件称为面板。

 

    JFrame 的结构并不是很复杂,图1.4-2说明了一个JFrame的组成。

 

(图1.4-2)

 

    你可以看到,JFrame 当中安排了两个窗格,上面的是标题栏(Title Bar),下面的是内容窗格(Content Pane)。程序员最关心的是内容窗格,当设计一个框架时,组件会被添加到内容窗格中,使用的代码类似于:

var contentPane:Container = frame.getContentPane();
var c:Component = ......;
contentPane.append(c);

 

    你不能直接往一个JFrame当中添加组件,而是应该向框架的内容窗格中放置。通过frame.getContentPane()可以得到框架的内容窗格。

 


 

  笔记:

 框架的内容窗格(Content Pane)是一个容器组件(Container)。Container是各种AsWing组件的容器,任何组件要可以显示,都必须添加到一个可以显示容器当中。 关于Container组件在后面的章节还会做详细的介绍。

 


 

 

    在我们的例子中,我们想把一个面板添加到内容窗格中。面板是用JPanel类实现的。这种用户界面元素具有两个有用的特性:

  • 有一个能在上面进行绘制的表面
  • 本身也是一个容器

 

    因此,它们还能容纳按钮、滑动条登其它界面元素。

 

    不过,把一个普通的JPanel添加到内容窗格当中是没有什么意义的——它什么都不能做。要使它变得有意义,必须使用继承来创建一个新类,然后通过覆盖或者添方法的手段来获得所需的额外功能。

 

    特别是,为了能在面板当中进行绘制,你需要:

  • 定义一个扩展(extends)JPanel的新类
  • 覆盖paint方法

 

    paint方法实际上定义在Component中,这个类是所有AsWing组件的父类。该方法将在组件会绘制的时候被调用。你可以在该方法中调用JPanel的graphics对象进行绘制。graphics对象储存了一个用于绘制矢量图形的设置集合(比如颜色,填充方式,透明度)。paint方法的IntRectangle类型参数指出了绘制的范围,你应该确保绘制只发生在这个范围之内。在组件的大小发生变化的时候,这个范围会随着改变,在范围内绘制可以保证你的图形总是正确地显示。

 

 


 

笔记:

JPanel当中的Graphics对象继承自ActionScript3.0核心类当中的Sprite类。所有的AsWing组件都是Sprite类的子类,但是你应该只是在特定的方法当中获取graphics对象进行绘制。

 


 

 

    下面的代码演示了如何创建一个可以在上面进行绘制的面板:

class HelloWorldPanel extends JPanel {

   public function HelloWorldPanel () {

   }
 

   override protected function paint(b:IntRectangle) : void{

      super.paint(b);
  

      var g:Graphics = this.graphics;

      ...... // 在这里写绘制代码

   }
}

 

    

    只要窗口需要重绘,不管是因为什么原因,事件处理器都会通知组件。它会引起所有需要重绘的组件中的paint方法被执行。

 

    绝不要自己调用paint方法。只要你的应用程序需要重新绘制,该方法就会自动调用。你不应该干涉这个过程。

 

    哪些类型的动作触发了这个自动过程呢?例如,用户缩放窗口或者改变组件的显示相关的属性比如背景色、字体等会引起重绘。如果一个组件的外观和自己的状态相关,那么组件状态发生变化时,也会被要求重绘,比如按钮的由弹起状态变为按下状态。(当然,当窗口首次显示时,它也需要处理那些指定如何绘制、在哪里绘制初始元素的代码。如果你的图形尺寸是是依赖于paint方法的IntRectangle类型参数的,那么在窗口尺寸发生变化的时候,图形的尺寸也会随之调整以适应窗口。

 

 


 

笔记:

如果需要强制性重绘屏幕,那么可以调用repaint方法。这个方法会让屏幕立即重新绘制以显示新的内容。

 


 

 

    在上面的代码段中可以看到,paint方法只有一个IntRectangle类型的参数。这个参数是一个矩形区域,它给定了绘制的范围。虽然AsWing并没有强制你只能在这个区域内绘制,但是你应该保证自己绘制的图形不要超出这个区域的边界。Graphics对象对屏幕的度量单位是像素。坐标(0,0)代表了你正绘制其表面的组件的左上角。

 

    显示一个圆形是最基本的绘制之一。Graphics类有一个drawCircle方法,其语法如下:

g.beginFill(color); 

g.drawCircle(x, y, radius);

    在绘制之前,需要先设置颜色,否则Graphics对象将会用最后一次设置的颜色来进行绘制。颜色值是一个6位的16进制整数,每两位分别代表一RGB的个颜色通道。比如,0xFF0000就代表红色(R=FF,G=00,B=00)。我们的例子当中显示的圆形是黑色的,它的颜色代码就是0x000000。

 

    在我们的例子中,我们需要在窗口的正中央绘制一个圆形。这个圆形正好内切框架的边缘。现在,我们的paint方法如下所示:

 

class HelloWorldPanel extends JPanel {

   public function HelloWorldPanel () {

   }
 

   override protected function paint(bounds:IntRectangle) : void{

     super.paint(bounds);
  
     var x:uint = bounds.x + Math.round(bounds.width/2);
     var y:uint = bounds.y + Math.round(bounds.height/2);
     var radius:uint = Math.max(10, Math.round(Math.min(bounds.width, bounds.height)/2));
  
     var graphics:Graphics = this.graphics;
     graphics.beginFill(0x000000);
     graphics.drawCircle(x, y, radius);

 

   }

}

 

    通过bounds可以获得绘制的区域大小,bounds会在框架大小发生变化的时候被重新设置以保证每次paint方法被调用的时候bounds都能正确反映绘制区域的大小,绘制的位置和尺寸应该根据bounds来计算。 

 


注意!

由于HelloWordPanel扩展了JPanel类,而JPanel类在paint方法中有自己的操作。为了确保超类完成自己的那份工作,我们必须在进行我们的绘制之前先调用super.paint方法。

 


 

 

 


 

笔记:

如果你的程序有大量的绘制工作,那么你应该用另外一种方式来进行绘制,我们将在后面介绍Graphics2D的时候介绍这种方式。

 


 

 

    例1-3给出了完整的代码

例1-3 HelloWorld.as

package
{
    import flash.display.Sprite;
 
    import org.aswing.AsWingManager;
    import org.aswing.Container;
    import org.aswing.JFrame;

 

    public class HelloWorld extends Sprite
    {
        public function HelloWorld()
        {
            AsWingManager.initAsStandard(this);
   
            var frame:JFrame = new JFrame();
            frame.setTitle("Hello World!");
            frame.setSizeWH(DEFAULT_WIDTH, DEFAULT_HEIGHT);
   
            var contentPane:Container = frame.getContentPane();
   
            var hello:HelloWorldPanel = new HelloWorldPanel();
            contentPane.append(hello);
   
            frame.show();
   
        }
  
  
        public static const DEFAULT_WIDTH:uint = 400;
        public static const DEFAULT_HEIGHT:uint = 300;
    }
}

 

import flash.display.Graphics;

 

import org.aswing.JPanel;
import org.aswing.geom.IntRectangle; 

 

class HelloWorldPanel extends JPanel {
    override protected function paint(bounds:IntRectangle) :void {
        super.paint(bounds);
  
        var x:uint = bounds.x + Math.round(bounds.width/2);
        var y:uint = bounds.y + Math.round(bounds.height/2);
        var radius:uint = Math.max(10, Math.round(Math.min(bounds.width, bounds.height)/2));
  
        var graphics:Graphics = this.graphics;
        graphics.beginFill(0x000000);
        graphics.drawCircle(x, y, radius);
    }
}

API:org.aswing.JFrame

  • getContentPane():Container

          返回JFrame内容窗格对象,该对象是一个容器组件对象(Container)

 

API:org.aswing.Component

  • repaint():void

          “尽可能快地” 重新绘制组件

  • paint(b:IntRectangle):void

          需要覆盖该方法来说明你的组件应如何绘制。参数b给定了一个绘制的范围,你应该保证绘制在这个范围内进行。


posted @ 2010-02-20 23:27  fxair  阅读(383)  评论(0编辑  收藏  举报