本章简介
传统网络应用是基于页面的,服务器端数据传递的模式,而且将网络程序的表示层建立于HTML之上,但是HTML只适合文本。因此,传统的,基于页面的系统已经越来越不适应使用者的全方位提要要求。富因特网应用程序(Rich Internet Application)便应运而生了。
Flex是一个针对RIA企业级应用的表示层解决方案,是一种应用程序框架,使用Flex可以针对Web应用程序的表示层开发,并加入各种绚丽的效果,此外flex能够很好的与Spring ,Hibernate等流行框架无缝集成,因而受到广泛的欢迎。
核心技能部分
RIA 是富网络应用(Rich Internet Application)的缩写,也即丰富互联网应用程序。它只是一种技术形式而不是具体的技术。
RIA 出现的背景
在 RIA 出现之前,软件开发都是基于 C/S(Client/Server)或 B/S(Browser/Server)架构,但两者各有缺点。
C/S 的主要缺点:
(1)开发、部署成本高:
传统 B/S 结构的软件需要针对不同 OS 开发对应的版本,且软件更新换代的速度越来越快自然成本会很高。
(2)维护成本高:
服务器和客户端都需要维护管理,工作量较大且技术支持复杂。
B/S 的主要缺点:
(1)受限于 HTML 技术,很难像 C/S 那样产生丰富,个性的客户端界面。
(2)存在浏览器兼容性差问题。
(3)Server 端负荷较重,响应速度慢。
绝大多数处理都集中在 Server 端,并且每次响应都要刷新页面(利用 Ajax 技术会有所缓解)。
随着软件的飞速发展,此时需要出现一种能够摒弃上述缺点的新的技术形式 – RIA 出现了。
RIA---富互联网应用程序,实际上我们可以把传统互联网应用中的浏览器是为“瘦“客户端,所有的业务操作和逻辑处理都由服务器端负责,客户端仅仅用来展现服务器反馈的静态数据。”请求-响应“模式导致用户不能流畅的操作web应用,降低了用户的体验和工作效率。
在旧式的C/S架构中,却从来没有遇到过这样的问题,因为他们使用另一个“聪明“的客户端,客户的所有操作都在客户端应用进行,客户端应用根据用户的操作执行复杂的运算和逻辑处理,只有在需要的时候才从后端数据库中获取数据,同时因为大量的资源文件安装在客户端,用户操作引起的页面变化也能迅速的展示出来,不需要任何服务器端的参与。只要运行在一个性能足够的计算机上,客户端的能力可以保证用户流畅的执行业务操作,没有远程服务器的参与,也就避免的了等待。但最终C/S演化成了B/S结构,走向了另一个极端,浏览器丧失了全部的数据分析处理能力,服务器包办了所有的业务操作和数据处理工作,甚至页面的生成工作也由服务器承担。
如果我们说C/S结构的客户端是“胖“客户端,而B/S结构式”瘦“客户端,RIA应用则是介于两者之间。RIA客户引擎仍然依赖B/S结构中的后端服务器的业务处理能力,但是同时更多的负担起了快速响应客户端操作,页面生成渲染和客户端数据分析处理等工作。”胖“客户端为RIA带来了许多好处。
丰富:胖客户端能够为用户提供更丰富的控件和工具,而不仅仅局限于传统的HTML控件,根据客户端引擎的不同,胖客户端能够不同程度的实现常见的客户端操作,例如拖拽,页面滚动等;
实时的数据处理: 客户端引擎使RIA应用拥有了智能的前端。客户端能够对本地拥有的数据,独立执行一定程度的运算和分析,而无须把所有的数据都发送回服务器,等待响应;
更好的响应:“胖“客户端能够携带必要的资源,同时,基于一定的缓存机制,能够及实地为客户生成并渲染响应界面,无须服务器端的参与;
服务器和客户端工作的重新分配:客户端分担了更多的工作,降低了向服务器端的请求频率,降低了服务器端的压力。
目前比较流行的 RIA 技术有以下三种:
Ø Adobe 的 Flex
Ø 微软的 Silverlight
Ø Sun 的 JavaFx
以上三种技术各有优势,本书只关注目前应用较广泛的 Flex。
Flex是Adobe公司发布的开源RIA开发框架。用于构建在 Adobe® Flash® Player 或 Adobe AIR® runtimes 环境内运行的跨浏览器、桌面和操作系统的富网络应用。
开发者可以使用开源免费的Flex SDK构建Flex应用程序,并通过使用Flex Builder 集成开发环境提高开发效率。
虽然对于 Flex 应用和多媒体应用都运行于 Flash Player 这同一平台,但对于动画、影音等多媒体应用仍然主要是美工或媒体制作者的工作,而 Flex 应用编程则完全是程序员的工作,可以说是两套面向不同需求的应用开发。在 Flex 的 GUI 编程中提供了和 Java、.NET、VB、Delphi 中相类似 UI 控件,诸如:输入框、按钮、树、面板、表格、菜单、日期、进度条、各类选择框等,并与这些传统语言相类似的界面控制机制,诸如:消息、触发动作(Action)等。一个熟悉 Java 编程的开发者,很容易过渡到 Flex 的开发,ActionScript 语言本身、甚至 Flex 中提供的很多类库都和 Java 相类似。从另外一个角度来看,一个 Flex 开发者完全不懂 Flash 制作也没有任何问题,Flex 应用仅仅是运行在 Flash Player 上而已。当然做为 Adobe 的统一解决方案,Flex 开发并不排斥对影音和动画等媒体的操作,实际上两者可以完美的结合。
Flex4 技术包含开源的Adobe Flex SDK、集成开发环境Flex Builder4、以及服务器端LiveCycle Data Service/Blaze DS。
Ø Flex SDK:包含了程序语言MXML和ActionScript,Flex组件类库及命令行方式的编译器。开发人员可以免费的使用Flex Sdk开发和部署Flex程序;
Ø Flex Bulider: 编译运行 Flex 的 IDE 工具,基于 Eclipse 开发。内置 Flex SDK 与 Flash Player4.0 命名为 Flash Builder。
Ø LiveCycle Data Service: 旧称“Flex Data Service“,Adobe服务器端技术,实现RIA应用和J2EE应用,服务器端业务逻辑 数据的集成。
Ø Flex 应用运行环境 – Adobe® Flash® Player 和 Adobe AIR® Runtimes两者都是运行环境,前者基于浏览器,后者基于桌面。可基于这两个环境开发 Flex 应用,但 Adobe® Flash® Player 已非常普及所以现有 Flex 应用绝大多数都是基于 Adobe® Flash® Player 开发。( Flex 3 要求 Flash Player 9 以上,Flex 4 要求 Flash Player 10 以上)。
Flash Builder4 是一个 基于Eclipes的集成开发环境,版本 4 之前称为 Flex Builder。用于帮助开发者使用 Flex 框架快速开发跨平台的富网络应用。Flash Builder4 已经集成了 Flex SDK,你不需要再额外下载安装它。
在 Windows 操作系统上安装 Flash Builder4:
Flash Builder4 安装文件有两种形式:”独立安装文件“(即安装文件已经包含 Eclipse)和“插件安装文件”(不包含 Eclipse)。以下只介绍插件形式的安装。
第一步:下载相关软件
下载 Flash Builder 4 高级版
网址http://ww.adobe.com/cfusion/tdrc/index.cfm?product=flash_builder在下拉菜单中选择“English | Eclipse Plug-in Windows | 403.3 MB”
点击“Download”按钮下载
第二步:安装
(1)安装 Flash Builder 插件之前关闭 Eclipse 和所有浏览器窗口;
(2)选择语言 见图1.1.1
图1.1.1 选择语言
(2)运行 Flash Builder 插件选择安装前的解压目录。见图1.1.2
图1.1.2 选择解压目录
(3)指定已经安装的 Eclipse 位置,点“Next” 见图1.1.3
图1.1.3
待执行完启动 MyEclipse ,在新建项目弹出窗口中会有“Flash Builder”一项,至此安装完毕.
创建Flex应用程序需要执行以下步骤:
(1)启动MyEclipes执行“文件“à”新建“à“other”à”Flex项目“ 弹出 ”新建Flex项目“对话框,在”项目名“文本框中输入项目名称”flexapp“即可。如图1.1.4所示:
图 1.1.4 创建flex应用
(2)单击完成按钮,flesh Builder将自动生成一个Flex项目,并自动创建一些基本文件,项目基本结构如图1.1.5所示:
图1.1.5 Flex项目文件结构
1) bin-debug文件夹:存放程序编译后输出的swf文件和html文件等。
2) html-template文件夹: 用来生成html页面的模板文件。
3) lib文件夹:库文件。
4) flexapp.mxml文件:项目的主程序文件。
打开flexapp.mxml文件,点击【设计】(Design)按钮进入设计视图。Flash Bulider提供了可视化的UI设计器,通过拖拽就可进行页面布局。
在左下角的【组件】(Components)面板中,拖拽Label,textInput ,button空间到设计区域,并在右侧的【Flex Property】(Flex属性)面板中,设置其各种属性,即可完成界面设计。整个过程如图1.1.6所示:
图1.1.6 UI设计
在进行拖拽开发的同时 Flex Bulider自动生成了如下MXML代码:
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
Application>
flexapp.mxml主程序文件就是一个标准的xml文件,后缀名为mxml。文件的第一行是xml声明。
(1)
(2)
(3)
为了实现登录的功能,还必须为登录按钮添加事件处理代码,最终代码如下:
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
import flash.net.navigateToURL; import mx.controls.Alert; protected function button1_clickHandler(event:MouseEvent):void { var name:String = this.uname.text; var pw:String = this.pwd.text; if(name=="alen"&&pw=="123"){ navigateToURL(new URLRequest("javascript:window.location='main.html'"),"_self"); } else{ Alert.show('用户名密码错误'); } } protected function button2_clickHandler(event:MouseEvent):void { navigateToURL(new URLRequest("javascript:window.close()"),"_self"); } ]]>
点击运行【Run】按钮,运行flexapp。Flash Builder将自动启动浏览器,打开一个html页面,这个页面中嵌入了flexapp.mxml所生的swf文件 如图1.1.7所示。
图1.1.7 编译运行
运行结果如图1.2.9所示,在用户名和密码两项中输入alen 和123 程序将登录成功并转入主页面否则将弹出提示框进行错误提示。
图1.1.8程序运行结果
默认情况下,Adobe Flash Build不发布源代码,在浏览器中无法执行查看源代码操作,在开发阶段可以使用【导出发行版】命令来发布Flex源代码,步骤如下:
(1)单击工具栏上的导出发行版图标,弹出对话框如图1.1.9,图1.1.10所示。
图1.1.9 导出发行版
图1.1.10 导出发行版
(2)在图1.2.10中,单击【完成】按钮,切换到代码视图,可以发现在flexapp.mxml中添加了如下代码:
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" viewSourceURL="srcview/index.html"> 运行程序,在浏览器中右键执行【查看源代码】,即可弹出源代码窗口,如图1.1.11, 1.12所示: 图1.1.11 查看源代码 图1.1.12 源代码窗口 MXML和ActionScript是编写Flex应用的程序语言。 Flex应用的一砖一瓦都由ActionScript搭建而成。Flex应用构建于ActionScript类库上。无论是按钮、下拉框、画布这些可视化控件或容器,还是数据模型、键盘操作管理器、HTTP连接服务这些非可视化组件,其背后都隐藏着ActionScript。 ActionScript是基于ECMAScript规范的程序语言,用来编写Adobe Flash及Flex应用。遵从ECMAScript规范的最著名脚本语言为JavaScript。从Flash Player 9开始支持的ActionScript符合ECMA-262,即第三版ECMAScript规范,但在类、命名空间、强类型变量及其他一些特性上作了大量扩展。这些ActionScript对ECMAScript规范的扩展,预计将会被包含在下一版的ECMAScript规范中。 但是单纯使用面向对象的程序语言编写用户界面是非常枯燥和低效的。声明性标记语言在这方面有更好的表现。MXML是符合XML语法规范的声明性标记语言,用来描述Flex应用界面的组件布局、属性和交互行为等。我们也可以使用MXML来描述非可视化组件,例如HTTP连接、数据绑定等。 为了更形象地说明,让我们先回到HTML世界。一个普通的HTML页面通常包含标签形式的HTML声明代码和更为复杂的JavaScript脚本。HTML说明了页面的布局、组件的属性等。JavaScript丰富了页面的交互行为,负责逻辑运算、事件响应,甚至服务器端数据交换。 Flex应用也很类似。MXML担负起HTML的责任,而ActionScript扮演类似JavaScript的角色,但比JavaScript要强大和复杂得多。 MXML标签实际上都对应着ActionScript类库的一个类或者类中的属性,程序在运行的时候,整个MXML将会被自动翻译成一个对应的ActionScript类。然后该类将会被编译成一个swf文件,并嵌入html中在浏览器内置的flashplayer中运行。 一个MXML文件实际上就是一个ActionScript类,可以使用代码动态的创建 ,也就是说MXML文件名可以直接作为一种自定义数据类型来使用,那么当然,MXML文件名称不能和已有的ActionScript类重名,这是显而易见的。Flex应用生成swf文件的过程如图1.1.13所示: 图1.1.13 Flex应用生成SWF文件原理 通过 keep-generated-actionscript 编译参数可以保存这些代码。这对学习Flex很有帮助。 右击项目,选择 【Properties】,选择【 Flex Compiler】 ,在【 Additional compiler arguments】: 下加上 -keep-generated-actionscript, 就会在在项目的 bin-debug 目录下将生成一个 generated 文件夹,里面便是你的application或者module或者titlewindow等mxml乃至整个应用运行时真正调用的as类。除了项目对应的 -generated.as 和 -interface.as 外,还有一些 Style.as 和 _properties.as,生成源代码的过程如图 1.1.14,1.1.15所示。 图 1.1.14 添加附加参数 图 1.1.15 生成的代码文件 这是一个对于Flex学习非常重要的功能,希望能引起大家的重视: (1)当研究MXML标记及其属性遇到疑问的时候,可以利用该功能查看MXML究竟被翻译成了什么代码。 (2)当遇到使用ActionScript开发组件遇到不会写的代码的时候,尤其是涉及到样式,皮肤,效果和事件等功能的时候,可以先写一个MXML文件,利用MXML实现其功能,然后查看翻译后的源代码,这样可以加快学习速度。 另外,生成的源代码可以在这里找到: Flex支持三种在MXM L中调用ActionScript的方式: Ø 内联方式; Ø 标签内嵌方式; Ø 使用 (1)内联方式 内联方式,就是直接在MXML标签中编写ActionScript代码。这种方式通常用来定义事件侦听器方法或者数据绑定。例如: < mx:Burton id=”mybutton” label= "welcome’ click="Alert.show(‘welcome)’> 上述代码中,当用户按下welcome按钮,FlashPlayer就会调用Alter类显示带有“welcome”消息的对话框。 当然,我们也可以用分号(;)分隔,加入多个ActionScript语句。 (2) 级联方式 用上述内联方式虽然可以加入多个ActionScript语句,但代码的可读性较低,而如果采用级联段的方式,则将使代码显得更清晰明了,而且可以在一个文件中重用ActionScript代码,可以在调用方法时传递参数。 例如:
import mx.controls.Alert; private function sayHello(param_name:String):void { Alert.show("Hello, "+param_name); } ]]> 我们使用 (3)外联方式 如果MXML文件中ActionScript代码特别大,我们可以考虑将代码提取出来,单独放到一个文件中;这样ActionScript代码和MXML文件分离,更易于维护。 将MXML文件中的ActionScript代码关联到一个外部文件中需要在MXML文件中进行设置,指定文件路径。这需要使用 import mx.controls.Alert; private function sayHello(param_name:String):void { mx.controls.Alert.show(“Hello, “+param_name); } 上述方式为AS方法单独新建一个as文件,然后设置该方法为被调用文件的Script元素的source属性值,并可以在调用方法时传递参数,此文件可以在多个文件调用,从而实现了AS方法在多个文件中的重用。 为了提高代码的重用性,降低维护的难度。可以将程序中功能独立或者需要反复使用的部分定义成一个用户自定义组件来使用,创建定制MXML 组件还可以简化构造复杂程序的过程。将程序划分为便于管理的块,可以编写并测试每个独立的组件。例如前例中的关闭窗口的按钮,在应用中被频繁的使用,那么就可以将其提取封装成一个自定义组件,以求重用。Flex中自定义组件的步骤如下: 在Flex应用程序中创建一个包命名为“view“,在包中存放自己的自定义组件。 执行【文件】à【新建】à【MXML组件】命令,弹出“新建MXML组件“对话框,按照提示输入各项,如图1.1.16所示: 图1.1.16 新建自定义组件 在图1.1.16中单击完成,并切换到代码视图输入以下代码: xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" label="关闭" click="button2_clickHandler(event)" >
import flash.net.navigateToURL; protected function button2_clickHandler(event:MouseEvent):void { navigateToURL(new URLRequest("javascript:window.close()"),"_self"); } ]]> 打开flexapp.mxml并切换到设计视图,可在左下角组件视图看到刚才定义的新组件,将其拖拽到指定位置即可。 切换回代码视图,可以发现生成了相应的代码,并自动引入了自定义控件 。 Flex中的组件无法脱离容器而对立显示,Flex组件必须放在某个容器中才能工作。 FleX应用就是用容器搭建起来的。组件是在容器中排列的。application是最外层的容器,在A}plication中嵌入各种容器和界面元素,容器中又可以再嵌套容器。我们把嵌套在容器中的组件称为容器的子项或子组件。就像我们使用div+css进行html的布局类似。 容器最重要的工作就是管理容器中组件的布局。对于大多数容器, Flex 会根据容器的布局规则 (如布局方向、容器填充和容器的子级之间的间隙) 自动定位容器中的控件,对于使用自动定位的容器, 直接设置其子组件的 x 或 y 属性或调用 move() 方法没有任何效果, 或仅有一个临时效果, 因为布局计算将组件的位置设置为一个计算的结果, 而不是指定的值。如果需要直接指定控件的位置,也可以通过指定容器的layout属性来实现。通过有效地使用容器,同时恰当地配合运用多个容器,可以对应用程序的外观实现最全面、最彻底、最有效率地控制。 可自动定位容器的layout属性有以下取值: (1)Basiclayout 绝对定位。 (2) HorizontalLayout 横向 水平定位。 (3) VerticalLayout 纵向垂直定位。 (4) TileLayout 网格定位。 Application是一个特殊的容器,位于界面元素层级的根部,包含整个程序中的所有元素,Application的Layout属性用于决定Application界面的布局 其默认值是绝对定位。 示例1中将Application容器设置为HorizontalLayout(横向定位),其常用属性:verticalAlign gap horizontalAlign paddingLeft等。 示例1: xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"> Panel容器是使用最广泛的一种容器,除了可以包含子元素,Panel容器还提供了标题栏区域,可以包含它的标题和状态信息,其默认布局是BasicLayout 示例3: xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"> 和panel类似 为了改进性能和最小化应用程序大小,不能设置 Group 容器的外观 其默认的布局管理器也是绝对定位。 示例4: xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"> Application> 运行程序效果如图1.1.19 图1.1.19 实现计算器界面 HGroup是一种只有HorizontalLayout布局的Group。 VGroup是一种只有VerticalLayout布局的Group。 Scroller也是一种容器 ,用于在Scroller中的内容边界超出Scroller后显示滚动条。 示例5:将group放在其中 如果有组件超出了group范围将出现滚动条。 xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"> 运行例5 效果如图1.1.20所示。 图1.1.20 使用sroller容器 Form容器是Flex 表单中处于最外层的容器,负责控制表单的大小,以及布局,通常表单中都是垂直布局,并且靠左对齐的。这个容器可以包含FormHeading以及FormItem。 示例6: xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"> 运行例6,效果如图1.1.21所示。 图1.1.21 使用表单布局 任务实训部分 训练技能点 创建Flex应用程序。 需求说明 创建Flex应用程序,实现计算器界面,用户通过按钮输入数字和运算符实现简单数学运算。 实现思路 (1)创建MXML应用程序,并设计功能接界面。 xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"> Application> (2)为数字按钮和运算符按钮添加事件处理代码。 xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
var temp : Number; var oper:String; protected function button1_clickHandler(event:MouseEvent):void { var tar: Button = event.target as Button; this.input1.text = this.input1.text+tar.label; } protected function button2_clickHandler(event:MouseEvent):void { var tar: Button = event.target as Button; temp = Number(this.input1.text); this.input1.text=''; this.oper= tar.label; } protected function button3_clickHandler(event:MouseEvent):void { this.input1.text=''; } protected function button4_clickHandler(event:MouseEvent):void { switch (oper){ case '+' : this.input1.text=(temp+Number(this.input1.text)).toString(); break; case '-' : this.input1.text=(temp-Number(this.input1.text)).toString(); break; case '*' : this.input1.text=(temp*Number(this.input1.text)).toString(); break; case '/' : this.input1.text=(temp/Number(this.input1.text)).toString(); break; } } ]]> (3)运行此应用 效果如图 1.2.1所示。 图 1.2.1 简单计算器 训练技能点 Ø 使用容器控制界面布局。 Ø 使用富文本编辑器控件。 Ø 使用下拉框控件。 需求说明 创建简单的文本编辑器,实现设置编辑器背景色和字体的功能。当文本超出编辑器的时候显示滚动条。 实现思路: (1) 创建MXML应用程序,设计文本编辑器界面。 xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
import mx.collections.ArrayCollection; private var mydb:ArrayCollection =new ArrayCollection([ {text:'宋体',value:'宋体'}, {text:'黑体',value:'黑体'}, {text:'楷体_GB2312',value:'楷体_GB2312'}, ]); ]]> (2) 为ColorPicker 和ComboBox控件添加change事件的处理代码以实现文本编辑器背景色和字体的设置。 xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
import mx.collections.ArrayCollection; import mx.events.ColorPickerEvent; import spark.events.IndexChangeEvent; private var mydb:ArrayCollection =new ArrayCollection([ {text:'宋体',value:'宋体'}, {text:'黑体',value:'黑体'}, {text:'楷体_GB2312',value:'楷体_GB2312'}, ]); protected function cp_changeHandler(event:ColorPickerEvent):void { this.ret.setStyle("backgroundColor",this.cp.selectedColor); } protected function cmb_changeHandler(event:IndexChangeEvent):void { this.ret.setStyle("fontFamily",this.cmb.selectedItem.value); } ]]> (3) 运行应用,效果如图1.2.2所示。 图1.2.2 简单文本编辑器 训练技能点 Ø 使用容器控制布局。 Ø 使用Timer定时器。 需求说明 实现简单的图片轮转浏览器。单击开始按钮 开始图片轮换,单击停止则停止轮换。 实现思路: (1)创建MXML应用程序,设计文本编辑器界面。 xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"> (2)为开始和停止按钮添加事件处理代码。 xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
private var timer:Timer; private var picindex:int=2; protected function button1_clickHandler(event:MouseEvent):void { timer=new Timer(2000); timer.addEventListener(TimerEvent.TIMER,doTimer); timer.start(); } protected function doTimer(event:TimerEvent):void { this.picindex++; if(this.picindex>6){ this.picindex=1; } this.img1.source="images/"+this.picindex+'.jpg'; } protected function button2_clickHandler(event:MouseEvent):void { this.timer.stop(); } ]]> 运行应用程序,效果如图1.2.3所示。 图1.2.3 图片轮换 训练技能点 Ø 表单布局的使用。 Ø 表单验证。 需求说明 完善用户注册表单,添加对表单的各种验证。 实现步骤: (1) 创建MXML应用程序,设计用户注册表单界面。 xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"> (2) 为表单添加各种形式的校验。 xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
import mx.controls.Alert; import mx.validators.Validator; protected function sub_clickHandler(event:MouseEvent):void { var check:Array = Validator.validateAll([v1,v2,v3,v4]); if(check.length!=0){ Alert.show("error"); return; } Alert.show("ok"); } ]]> (3) 运行应用程序,效果如图1.2.4所示。 图1.2.4 表单校验 巩固练习 选择题 1. 以下不属于RIA概念的是 () A. RIA将桌面应用程序的强交互性与传统的WEB应用的灵活性综合起来。 B. RIA的富客户端采用异步的方式和服务器进行交互。 C. RIA可以整合声音 视频等桌面元素。 D. RIA通信中会传输所有数据,加重了数据传输负担。 2. 以下关于Flex程序的说法,正确的是 () A. Flex程序由*.MXML *.as *.css文件组成。 B. MXML语言专用于Flex程序中,是用于描述界面表现的一种XML标记语言。 C. ActionScript 是针对Adobe Flash Player运行环境的编程语言。 D. MXML提供了一系列标签供用户使用,MXML不区分大小写。 3. 以下关于Application布局的说法,正确的是()。 A. Application默认布局是BasicLayout。 B. HorizontalLayout 表示水平布局。 C. VerticalLayout表示竖直布局。 D. Tilelayout表示主题布局方式。 4. 关于以下代码的说法,正确的是()。 A. 当用户单击提交按钮的时候,触发验证对象。 B. 当用户单击id为submit的按钮,触发验证对象。 C. 验证对象验证的目的是id为txtpwd的组件。 D. 验证对象验证的属性是txtpwd的text属性。 学习内容 Ø ActionScript 3.0语法基础 Ø ActionScript3.0面向对象编程 能力目标 Ø 掌握ActionScript3.0的基本语法 Ø 能够熟练使用ActionScript3.0解决问题 本章简介 本章将学习ActionScript 3.0语法基础 ,ActionScript的动作脚本是遵循ECMAscript 的Adobe Flash Player运行时环境的编程语言,它在Flash内容和应用程序中实现交互性、数据处理以及其他功能。ActionScript是Flash的脚本语言,与JavaScript相似它是一种面向对象编程语言。语法和js的相似度很高,因此本章将着重从两者的不同之处入手讲解最常用的基本语法,本章大家将会学习到As的数据类型,流程控制,面向对象语法和一些常用类。 核心技能部分 ActionScript动作脚本是遵循ECMAscript的Adobe Flash Player运行时环境的编程语言,它在Flash内容和应用程序中具有实现交互性、数据处理以及其他功能。ActionScript是Flash的脚本语言。与JavaScript相似,ActionScript是一种面向对象编程语言。ActionScript是开发Flex应用使用的脚本语言。 ActionScript3.0是运行于Flash Player运行环境的编程语言。使用新的ActionScript虚拟机AVM2。使用新的二进制指令集,在性能上有很大的改进。同时,使用面向对象模型,扩展和提高了应用程序接口。ActionScript3.0代码被Flash Builder或者Flash中的编译器编译成二进制数据。这种二进制数据被装入SWF文件中,然后运行于Flash Player运行环境中。 ActionScript3.0继承之前的ActionScript版本,并有了较大的更新。ActionScript3.0中包含大量的数据、对象和可重用代码,能开发出更加复杂的应用程序,且执行效率大大提高。 虽然ActionScript3.0包含的许多类和组件同之前的版本名称相同,但是类和组件在ActionScript3.0中更结构化,这与之前的ActionScript版本还是有很大的不同。此外,ActionScript3.0中许多核心类新增了许多属性和方法,Flash Player中也新增了许多对底层对象的控制。 ActionScript 3.0(以下简称AS 3.0)的数据类型按结构可以分为两种:原生数据类型和复杂数据类型。其中,原生数据类型是组成所有数据类型的核心,AS3.0语言本身提供如字符串、整型、布尔类型等。复杂数据类型可以理解为构造类型,是由基本数据类型组成的复合数据类型,如类、 接口等。AS 3.0中的原生数据类型见表9-1-1。 表9-1-1 原生数据类型 类型名 类型描述 Boolean 布尔类型.只能取值true或false int 整数类型,存放32位二进制整数,取值范围是-2147483648~2147483647 Null 只有null值,代表空值,是字符串类型和所有类的默认值。不能作为类型修饰符 Number 整数类型和浮点类型,使用64位双精度格式存放数据。没有小数点时自动转为整数类型 String 字符串类型 uint 正整数类型.取值范围是0-4294967295 void 值为undefined,只可以用作函数的返回类型 除了表9-1-1中的原生数据之外,AS 3.0还提供了一些复杂的数据类型,如Object(对象)、Array (数组)、Date(日期)、Error(错误)、Function(函数)、XML和XMLLIST。其中,Object是所有对象的基类。 每种数据类型都有默认值,一旦变量确定了类型,就被赋予一定的值。其中,复杂类型( Object、 Array等)和字符串默认值为null,Number默认值为NAN,int和uint默认值为0,布尔类型默认值为false。如果某个变量的类型不确定,可以将其类型设置为“*”(变体类型)。例如,以下代码将定义一个变量tmp为变体类型: private tmp:*; 定义后,tmp变量将可以赋予多种数据类型的常量,Flash Player会自动进行转化。 在AS 3.0中,String类完成了所有的字符处理工作。字符串声明的方法包括3种,以声明字符串 “hello”为例,3种方式分别如下: str:String='hello'; str:String="hello"; str: String=new String ( "hello" ) ; 当字符串中包括双引号、单引号和字符串的引号冲突时,“\”表示将后面的字符视为普通字符。 var str: String=‘hello\’word'; var str:String=“hello\”word"; String类的length属性用于返回字符串的长度。此外,String类还提供了以下5个方法操作字符串 (1)contact(...args):用于合并字符串并返回一个新的字符串,且不修改原字符串。其中, “args”表示不定参数,代表零个或多个参数。执行以下代码,在调试状态下,控制台将输出“abcd1234”。 var str:String = “ab”; var str1:String = str.contact(“cd”,“12“,“34“); trace(str1); (2)charAt(index):用于获取指定位置的字符。其中,index表示字符位置索引,字符的位置索引从0开始。执行以下代码,在调试状态下,控制台将输出“a”: var str:String="abcd"; var strl:String=str.charAt (0) ; trace ( strl) ; (3) indexOf(val,startlndex):用于查找指定字符串并返回查询结果的第一个位置,startlndex 表示查询的起始位置,默认为O,表示从字符串的开头开始。执行以下代码,在调试状态下,控制台将输出“1”: var str:String="abcd"; var subStringIndex:int=str. indexOf(”bc”); trace( subStringIndex); (4) split(delimiter,limit):用于以参数delimiter为分割符将字符串切分为数组,参数limit表示限制返回数组中元素的数目。执行以下代码后,在调试状态下,控制台将输出“###”: var str:String=”***,###,&&&¨; var splitArr:Array=str.split(¨,¨); trace( splitArr[1]); (5)substr(startlndex,len)、substring(startlndex,endlndex):用于截取字符串。其中,substr方法表示 从startlndex位置开始截取长度为len的字符,省略Ien则表示截取startlndex位置后的所有字符串。substring方法表示截取从startlndex位置到endlndex位置的字符串,省略endlndex则表示取从startlndex位置后的所有字符串。 var str:String-"abcdefg"; var substrl: String=str. substr (2) ; var substr2 : String=str . substr ( 2,3) ; var substr3 : String=str . substring { 2) ; var substr4 :String=str. substring (2,3 ) ; traca ( substrl) ; trace (substr2) ; trace (substr3) : trace (substr4) ; 在调试状态下,执行上述代码将在控制台输出: cdefg cde cdefg c 在程序中,经常要进行数字计算。AS 3.0中除了常规的运算符外,还提供了Math类,实现了绝大部分的数学计算公式。AS 3.0提供的算术运算符见表9-1-2。 表9-1-2 AS 3.0算术运算符 符号 说明 符号 说明 + 加法运算 ++ 自加运算 - 减法运算 -- 自减运算 * 乘法运算 *= 连乘运算 / 除法运算 /= 连除运算 % 取余运算 %= 连取余运算 另外,使用Math类还可以进行更复杂的计算。Math类常用的方法如下: (1)Math.round(n):对指定的数字进行整数的四舍五入。例如,执行以下代码后在调试状态下, 控制台将输出“13”。 var vl:Number=12.54; var result :Number=Math . round (vl) ; trace (result) ; Math类的round方法只能对整数进行四舍五入,可以使用Number提供的toFixed(n)方法实现小数的四舍五入,传入一个需要保留小数位数的参数、返回一个字符串类型的值。执行以下代码: var vl:Number=12.54; var resultl:String=vl toFixed (1) ; var result2 :String=vl. toFixed ( ) ; trace ( resultl) ; trace (result2) ; 执行后,在调试状态下,控制台的输出结果为: 12.5 13 (2) Math.floor(n)、Math.ceil(n):向上或向下取整。其中,floor(n)方法表示向上取整,而ceil(n) 方法表示向下取整。执行以下代码: var vl:Number=12.54; var resultl:Number=Math. floor (vl) ; var result2 :Number=Math . ceil (vl) ; trace ( resultl) ; trace ( result2) ; 执行后,在调试状态下,控制台的输出结果为: 12 13 (3)Math.max(vall,va12,…rcst)、Math.min(vall,va12,…rest):计算给定数字的最大值与最小值。 (4) Math.random():用于产生一个随机数n,取值范围为0<=n<1。执行以下代码: var vl:Number; vl=Math. floor (Math. random ( ) *90+10) ; trace (vl) ; vl=Math. floor ( Math . random ( ) *90+10) ; trace (vl) ; vl=Math . floor (Math . random ( ) *90+10 ) ; trace (vl) ; 执行后,在调试状态下,控制台的输出结果为: 80 66 75 上述结果为3个10~100之间的随机整数。 在AS3.0中可以使用 parseInt() 函数把字符串转换为十进制数,用 Number, uint, 或 int 对象的 toString() 方法 转换为字符串。 下面的代码用构造uint对象,输出不同的格式: // radix 为 2, 输出二进制 trace(new uint(51).toString(2)); // 显示: 110011 // radix 为 16, 输出十六进制 trace(new uint(25).toString(16)); // 显示:19 var quantity:Number = 164; trace(quantity.toString(16)); // 显示: a4 toString() 方法的参数值的合法范围在2到36,如果没有指定参数值,默认为10。 和 toString() 相反的是 parseInt() 函数。它把指定的字符串转换为数字。 下面的代码把各种字符串,输出十进制数。 trace(parseInt("110011", 2)); // 显示: 51 trace(parseInt("19", 16)); // 显示: 25 trace(parseInt("17", 10)); // 显示: 17 如果不指定字符串进制,默认为十进制,除非在字符串前加上0x, 0X, 或0: trace(parseInt("0x12")); // 显示: 18 trace(parseInt("017")); // 显示: 15 下面的代码给出的字符串格式和指定进制冲突,这时会默认为十进制 // 但是下面的字符串是不合法的数字,因此返回0 trace(parseInt("0x12", 10)); // 显示: 0 下面的字符串为八进制,但指定为十进制,因此系统默认字符串为十进制,而不是八进制。 trace(parseInt("017", 10)); // 显示 17 race(parseInt("A9FC9C")); // NaN (1)创建数组。 Ø 创建数组就是创建Array类的一个实例。 var tmpArr :Array=new Array ( ) ; Ø 创建数组时可以初始化数据: var bookArr :Array=new Array ( " java", "jsp", " flex" ) ; Ø 创建数组还可以使用中括号的形式,此方式为简便方式。例如.声明数组bookArr的代码如下: var bookArr:Array= [ ] ; 同样,可以使用中括号初始化数据。以下代码将声明一个数组bookArr,并初始化数据: var bookArr:Array= [" java", "jsp", " flex" ] ; (2)访问数组元素。数组的元素通过下标完成,下标总是从0开始。执行以下代码: var bookArr :Array= [ " java", "jsp" , " flex"] ; var tmpArr :Array= [ ] , tmpArr.push (10) tmpArr.push (20) ; trace (bookArr [0] ) ; trace (tmpArr [1] ) ; 其中,push()方法表示将数据添加到数组的尾部。执行后,控制台在调试状态下的输出结果为: java 20 ArrayCollection对象作为Flex组件的数据提供者十分实用,如填充列表框等。当修改用于数据绑定的ArrayCollection时,组件显示会随着底层数据的更改而自动更新。但Array中的数据发生更改时组件不会自动更新。 (1)创建ArrayCollection对象,可以通过MXML标签和ActionScript两种方式完成。 Ø 使用ActionScript创建。例如,创建一个书籍的ArrayCollection对象,并输出其中的值: var bookArrayCollection: ArrayCollection=new ArrayCollection([{bookId:"B001",bookName: "JAVA"}, {bookId: "B002",bookName: "JsP"}, {bookId: "B003",bookName: "FLEX"} ]); trace( bookArrayCollection[0].bookId); trace (bookArrayCollection[1].bookName); 在调试状态下,以上代码将在控制台输出结果如下: BO01 JSP Ø 使用MXML标签创建。 (2)使用ArrayCollection组件。 示例2.1 xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" >
import spark.events.IndexChangeEvent; import mx.controls.Alert; //处理单击加载按钮事件 protected function btnLoad_clickHandler (event:MouseEvent):void { //设置AdvancedDataGrid组件的dataProvider属性为bookArrayCollection this.adg1. dataProvider=this.bookArrayCollection; } //处理单击“删除”按钮事件 protected function btnDel_clickHandler(event:MouseEvent):void { //获取用户选择行的书籍编号 var selIndex:int=this. adg1. selectedIndex; if (selIndex<0) { Alert.show("没有选择行", 'bookArrayCollection组件使用方法示例演示'); return; } this. bookArrayCollection. removeItemAt( selIndex); } //处理用户在下拉枢中选中项改变时的事件 protected function ddlBookType_changeHandler ( event: IndexChangeEvent): void { //如果用户选择“显示全部”,则不用过滤 if (this.ddlBookType.selectedItem=='显示全部') { this. bookArrayCollection. filterFunction= null; } else { //根据类别过滤bookArrayCollection this . bookArrayCollection . filterFunction=doArrayCollectionFilter; } //刷新bookArrayCollection this.bookArrayCollection.refresh() ; } private function doArrayCollectionFilter(item:Object):Boolean{ //开始过滤 return item.bookType==this.ddlBookType.selectedItem; } ]]> selectedIndex="0" change="ddlBookType_changeHandler(event)" /> 示例2.1结合 图2.1.1 ArrayCollection组件演示 在图2.1.1中,单击“载入数据”按钮可以加载bookArrayCollection数据到AdvancedDataGrid中;单击“删除数据”按钮可以删除AdvancedDataGrid中选中的行;单击“选择类型”下拉框, 可以根据书籍类型过滤AdvancedDataGrid中的数据。 (1) if流程控制。 语法: if(条件表达式){ 代码块 } if(条件表达式){ 代码块 } else { 代码块 } if(条件表达式) { 代码块 } else if(条件表达式) { 代码块 } else if(条件表达式){ 代码块 } else { 代码块 } (2) switch流程控制。对if语句使用多重嵌套往往会降低程序的可读性,此时可以使用switch语句代替,它是多分支的选择语句。 语法: switch(条件表达式){ case值1: 代码块 break; case值2: 代码块 break; ..... default: 代码块 } AS 3.0中共有5种循环类型。 (1) for循环。 语法: for(表达式1;表达式2;表达式3) { 代码块 } 执行以下代码: for (var i:int=l; i<=3; i++) { trace (i); } 执行后,在调试状态下,控制台的输出结果为: 1 2 3 (2) for…in循环:主要用于遍历一个对象中的属性集合。 语法: for(var属性名in对象) { //对象名[属性名] ) (3) for each…in循环:主要用于遍历数组或获取对象的属性值。 语法: for each(var元素in 集合) { 代码块 ) 执行以下代码: var bookArrayCollection:ArrayCollection=new ArrayCollection ( [ { bookId : "BOO1”, bookName : "JAVA" } , { bookId: "B002 " , bookName : "JSP" } , { bookId: "B003", bookName : "FLEX" } ]); //for each用于遍历bookArrayCollection数组中的元素 for each (var element in bookArrayCollection) { //element代表bookArrayCollection数组中的每一个元素 for (var prop in element) { //for in用于遍历element对象的所有属性,其中prop代表element中每个属性 //通过element[prop]的形式即可输出对应的属性值 trace (element[prop]); } } 执行后,在调试状态下,控制台的输出结果为: JAVA BO01 JSP B002 FLEX B003 上述代码中,也可以将以下代码使用for each…in循环进行替换: for (var prop in element) { trace (element [prop]); } 替换后的代码如下: for each(var propValue in element) { //propValue代表element中的每一个属性值 t race( propValue) ) (4) while循环:与for循环类似。 语法: while(条件表达式){ 代码块 } (5) do…while循环。 语法: do { 代码块 ) while(条件表达式) 值得注意的是,在Flex循环中可以使用break和continue语句。其中,break表示强制退出循环。 而continue表示结束本次循环. 面向对象是AS 3.0的基础,本节将介绍面向对象的基本语法知识。 在ActionScript中,类以“as”为后缀的文件存在,且文件名和类名相同。虽然Windows系统不区分文件大小写,但ActionScript除外,因此文件名和类名必须绝对一致。创建类的语法为: package 包名{ 修饰词class 类名{ 代码块 } } 上述语法中,package代表类所属的包,一个类必须放在包中。在同一个程序中,当定义的类很多时,为了便于管理,可以将功能相同的类放在一个包中。例如,以下代码定义了类Example, 位于“tree”包中: package tree{ public class Example( //类的主体代码 } } 保存文件,命名为“Example.as”,在主程序目录下创建tree包,并添加上述as文件。一个as文件类中只能有一个public类型的类,且文件名必须和类名保持一致。在AS 3.0中,类共有4种修饰词: Ø public:公有类型,使用该修饰词定义的类可以被任何作用域内的任何对象访问,即没有任何访问限制。一般用于定义全局使用的类。 Ø intemal:默认的修饰词,表示在内部使用类,其用法与public相似。但是,对类的访问和操作只限定在同一个package中。 Ø dynamic:动态类型,类的属性和方法不确定,允许在运行时动态地添加。动态类型很少使用,一般只用于特殊场合。 Ø final:终点类型,表示类是继承关系中的终点,不能被继承,无法修改属性和方法,因此i 以视为一个固定的、无法被动态修改的常数。 创建类后,就可以使用类来实例化对象。 语法: var对象名:类名=new类的构造函数; 上述语法中,var关键字用于声明一个变量或对象,不使用var定义的变量或对象时,编译器会医无法识别而报错。当使用的类和定义其对象的代码不在同一个包中时,需要首先引入类,Flex使用import关键字完成该动作。例如,import tree. Example。 在面向对象的语言中,类由属性和方法组成,方法对应一个函数。 (1)定义一个类Example,并为其增加一系列方法。 示例2.2 package tree { public class Example { //定义成员变量str private var str:String; //类的构造方法 public function Example() { this .str=str; } //定义类的函数方法,设置str值 public function setStr(str:string):void { this.str=str; } //定义类的函数的方法,获得str值 public function getStr():String { //通过return语句返回值 return this.str; } } (2)在ActionScript3.0中,方法共有4种修饰词,分别是public private protected和internal。 Ø public:共有类型,表示可以被所有的类使用,无论类是否在同一包中。 Ø protected:保护类型,定义的方法可以在其内部或者子类的内部使用。 Ø private :私有类型,最严格的类型,只能在类的内部使用,外部不可见。 Ø internal:内部类型,限定在同一包中使用。 (3)方法参数的默认值:定义函数的参数时,可以设置参数的默认值,放置错误的调用,如果调用函数时没有传入该参数,则使用默认值。 示例2.3 public function doTest(str:String=’hello’):void{ 代码块 } 示例2.3中将参数str的默认值设为“hello”,调用该方法时,如果没有为str参数指定值.则Felx 会自动采用为其设置的默认值。 (4)方法的不定参数 AS 3.0还支持函数方法的不定参数,参数的个数可以动态变化。不定参数使用“…args”形式:其中的args是一个数组,存放了所有的多余参数。 示例2.4 public function doTest (str : String,...args) :void { trace (str) ; for each (var element in args) { trace (element) ; } } 示例2.4中,在调用函数方法时,传入多个参数: doTest(“a”, “b”, “c”, “d”, “e”); 在调试状态下,输出的结果为: a b c d 由输出结果可知,除了第一个参数外,后面的参数都被放在args变量中。循环遍历args可以访问到所有的参数。 (5)静态方法 定义静态方法只要在定义方法时加上static关键字即可。静态方法属于类,而不是对象。调用静态方法时,可以通过“类名.方法名”实现。例如,定义一个静态方法setValue,代码如下: public static function setValue (str:String):void { trace (str); } 可以通过Example.setValue("hello")形式直接调用静态方法setValue。 类的继承是面向对象编程思想精髓。继承类需要使用关键词extends。 语法: public class subClass extends parentClass 示例2.5 定义父类: package tree { public class ParentClass //定义父类 { //定义父类的protected类型变量 protected var objvalue:string; //父类的构造方法 public function ParentClass() { } //父类 getObj Value方法 public function getObjValue() :String { return this.objvalue; } //父类 setObjValue方法 public function setObjValue(value:string) { this.obj value=value ; } } } 定义子类: package tree{ //定义予类 //继承自于ParentClass父类 public class SubClass extends ParentClass { //子类的构造方法 public function SubClass () { super();//super关键字,表示引用父类的实例 } //使用override关键字覆盖父类的同名setObjectValue方法 Override public function setObjectValue(value:String){ //先调用父类的setObjValue方法 super .setObjValue (value); this.objvalue+=value; } } } 使用子类: var subClass : SubClass=new SubClass ( ) ; subClass.setObjValue ("** ") ; trace ( subClass .getObj Value ()) ; 示例2.5演示了Flex中的继承特性,执行以上代码后,在调试状态下,在控制台将输出: **** AS 3.0中没有提供定义抽象类的方法,但可以使用接口(Interface)实现类似的功能。 示例 2.6 package tree { //定义接口 public interface IExample { //在接口中定义方法 function start (task:String):void; function stop( task: String):void; } } 定义接口后,需要创建其实现类。定义一个实现类MyExample类,用于实现上述定义的IExample接口。 示例2.7 package tree { public class MyExample implements IExample { public function MyExample() { //代码块 } public function start (task:String):void { //代码块 } public function stop (task:String):void { //代码块 } } } Flash 播放器 8.5 开始支持 try/catch 方法来处理错误。这意味着可以灵活的处理遇到的错误 了。除了语法错误(这时编译器就通不过),其他类型的错误如非法数据等都可以自己处理。 处理异常包括两个部分,抛出异常和捕获异常。有些异常系统会自动抛出,比如 IllegalOperationError, MemoryError, 和 ScriptTimeoutError. 它们都在 flash.errors 包 中 。除 了系 统定义的错误外也可以抛出自定义错误,然后捕获它进行处理。使用 throw 语句抛出一个Error 对象或Error 子类实例,比如: throw new Error("A general error occurred."); 正如我们看到的,Error 构造器接受一个参数,这个信息和这个错误相关联。这个参数是可选 的,依赖于你怎样处理这个错误,你可以不使用,但是大多数情况下都指定一个错误信息作为 调试目的。 一旦异常被抛出,Flash就会暂停当前进程去寻找 catch 块去处理异常。任何有潜在错误的代码 都要放在 try 块中,如果异常抛出,只有它所在的 try 块被暂停,然后相关联的 catch 块被调 用,看下面的例子: try { trace("This code is about to throw an error."); throw new Error("A general error occurred."); trace("This line won't run"); } catch (errObject:Error) { trace("The catch block has been called."); trace("The message is: " + errObject.message); } 上面的代码数出以下信息: This code is about to throw an error. The catch block has been called. The message is: A general error occurred. 当然,上面的代码还是过于简单,但是这是个基本框架,可以看到只要抛出异常,try 块就会退出,catch 块被执行,传递了一个 Error 对象给 catch. 更多情况下,异常是从函数或方法中抛出的, Flash 会检测该函数是否在 try 块内被调用,如 果是,则调用相应的 catch 块。 private function displayMessage(message:String):void { if(message == undefined) { throw new Error("No message was defined."); } trace(message); } try { trace("This code is about to throw an error."); displayMessage( ); trace("This line won't run"); } catch (errObject:Error) { trace("The catch block has been called."); trace("The message is: " + errObject.message); } 上面的代码输出以下内容: This code is about to throw an error. The catch block has been called. The message is: No message was defined. 如果你不肯定你的函数或方法会在何时或如何抛出异常,这时就应该在try块进行调用。 // 定一个在指定的sprite里的画矩形函数。 private function drawRectangle(sprite:Sprite, newWidth:Number, newHeight:Number):void { // 检测长和宽的数值是否合法,否则抛出异常。 if(isNaN(newWidth) || isNaN(newHeight)) { throw new Error("Invalid dimensions specified."); } // 如无异常,则画出矩形 sprite.graphics.lineStyle(1, 0, 1); sprite.graphics.lineTo(nWidth, 0); sprite.graphics.lineTo(nWidth, nHeight); sprite.graphics.lineTo(0, nHeight); sprite.graphics.lineTo(0, 0); } 现在我们在 try/catch 语句内调用该函数。 try { drawRectangle(this, widthB, heightB); } catch(errObject:Error) { this.graphics.clear( ); tOutput.text = "An error occurred: " + errObject.message; } 另外对于try/catch 语句,还可以加入 finally 块,finally 块包含的代码无论是否遇到异常都会 被执行。例如下面的两个例子效果相同: //没有使用finally: private function displayMessage(message:String):void { try { if(message == undefined) { Throw new Error("The message is undefined."); } trace(message); } catch (errObject:Error) { trace(errObject.message); } trace("This is the last line displayed."); } //使用 finally: private function displayMessage(message:String):void { try { if(message == undefined) { throw new Error("The message is undefined."); } trace(message); } catch (errObject:Error) { trace(errObject.message); } finally { trace("This is the last line displayed."); } } 如果在catch中使用了return语句,那结果就不一样了: //没有使用finally: private function displayMessage(message:String):void { try { if(message == undefined) { throw new Error("The message is undefined."); } trace(message); } catch (errObject:Error) { trace(errObject.message); return; } // 这一句没有执行. trace("This is the last line displayed."); } //使用 finally: private function displayMessage(message:String):void { try { if(message == undefined) { throw new Error("The message is undefined."); } trace(message); } catch (errObject:Error) { trace(errObject.message); return; } finally { // 执行,不管是否有异常发生。 trace("This is the last line displayed."); } } 日期和时间对于很多AS3.0程序来说是很重要的,比如用于一些和时间相关的定时操作, 或者检测用户的登陆是否过期等。 在ActionScript内部是以毫秒的形式存储日期和时间的,但是很多编程语言的日期和时间是以秒为单位的,这点需要注意。 另外,Date 类用于设置或获取日期和时间,或者直接通过其属性 fullYear, month 等,这些属性的值也是以毫秒为单位的。 (1)获得当前日期和时间 在AS3.0使用Date() 创建一个date对象,或者使用一个CGI脚本或其他服务端脚本返回服务器时间,然后根据返回值创建date对象 AS3.0计算出来的日期和时间是根据客户端计算机的日期和时间而得出的,因此如果客户端的时间不正确,那么date对象也是不正确的。 示例2.8 // 创建新的Date对象 var current:Date = new Date( ); // 显示客户端日期和时间 trace(current); 如果你连接上了互联网,Flash可以从服务器获得日期和时间,这项技术可以保证获得正确的日期和时间(当然了你也可以故意把服务器时间设置错误,但是至少可以保证所有的客户端的时间是一致的)。 一般从服务器获得时间的步骤如下: 在Web服务器上创建CGI脚本,输出时间(秒)。使用flash.net.URLLoader对象读取时间。转换数值为number类型,再用这个数值重新构造一个date对象。 不管你使用什么服务端脚本,最后都要用ActionScript的flash.net.URLLoader对象载入服务器返回 的时间值。 示例2.9 新建一个Servlet,路径为/getdate,内容很简单,如下: response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print(System.currentTimeMillis()); out.flush(); out.close(); As代码如下: package { import flash.net.URLLoader; import flash.net.URLRequest; import flash.events.Event; public class ServerDateTimeExample { public function ServerDateTimeExample( ) { // 下面的代码创建一个URLLoader对象,添加一个监听器,当数据载入完成时激活onDateTimeLoad( )方//法 var loader:URLLoader = new URLLoader( ); loader.addEventListener(Event.COMPLETE, onDateTimeLoad); loader.load(new URLRequest("http://localhost:8080/L8WEb/getdate")); } private function onDateTimeLoad(event:Event):void { var loader:URLLoader = URLLoader(event.target); var data:Number = Number(loader.data); var current:Date = new Date(data ); trace(current); } } } (2)获取时间值 使用Date类的fullYear, date, month, day, hours, minutes, seconds, milliseconds 等属性就可以取得相应的时间。 Ø fullYear 属性返回4位数的年份值,如2010. Ø date 属性返回月天数,如1 到 31. Ø month 属性返回月份,如0 (1月) 到 11 (12月). Ø day 属性返回星期天数,如0 (星期天) 到 6 (星期六). Ø hours 属性返回小时数,如 0 到 23. minutes 和 seconds 属性返回值为0 到 59 (3)获取星期天数和月份名称 ActionScript的Date类提供了day和month属性,它们返回整数值如星期(0到6), 月 份 ( 0到11)。但是如果想获得名称而不是数字的话就需要自己创建包含星期天数和月份的名称数组,或者使用自定义类ascb. util.DateFormat。它已经定义了DAYS, DAYS_ABBREVIATED, MONTHS, 和MONTHS_ABBREVIATED 等数组,细节如下: public static const DAYS:Array = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; public static const DAYSABBREVIATED:Array = ["Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"]; public static const MONTHS:Array = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; public static const MONTHSABBREVIATED:Array = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; 具体使用如下: var example:Date = new Date(2010, 3, 10); trace(DateFormat.DAYS[example.day]); // 显示: Saturday trace(DateFormat.DAYSABBREVIATED[example.day]); // 显示: Sat trace(DateFormat.MONTHS[example.month]); // 显示: April trace(DateFormat.MONTHSABBREVIATED[example.month]); // 显示: Apr (4)格式化日期和时间 使用Date.toString(), 或者使用DateFormatter类, Date.toString() ,Date.toLocalString等方法返回Date对象的字符串类型数值,比如: // 显示: Tue Jan 5 14:25:20 GMT-0800 2010 trace((new Date()).toString()); 如果忽略toString()方法,ActionScript 也会自动调用toString()方法。 Date类本身并没有内建一些格式化日期和时间的方法,可以自己去实现。 var example:Date = new Date(2010, 0, 5, 10, 25); var formatted:String = (example.month + 1) + "/" + example.fullYear; trace(formatted); // 显示: 1/2010 这样的话,每次转换都非常的麻烦,我们可以使用mx.formatters.DateFormatter来进行Date的和字符串之间的相互转换。示例2.10演示了DateFormatter的使用。 示例2.10 var df:DateFormatter = new DateFormatter(); df.formatString="YYYY-M-D"; var dateStr:String=df.format(new Date()); trace(dateStr); var date:Date = DateFormatter.parseDateString(dateStr); trace(date+''); (5)使用 Timer(定时器) flash.util.Timer 类允许通过添加时间事件或延时来调用方法。通过Timer构造器创建实例对象, 传递一个毫秒数字作为构造器参数作为间隔时间,如果想通过一定的间隔或一定的延时轮询某个方法就 可以使用flash.util.Timer 类来实现。 下面代码实例化一个Timer对象每隔1秒钟 发出事件信号: var timer:Timer = new Timer(1000); 一旦创建了Timer实例,下一步必须添加一个事件监听器来处理发出的事件,Timer对象发出一 个flash.event.TimerEvent 事件,它是根据设置的间隔时间或延时时间定时发出。下面的代码定 义了一个事件监听器,调用onTimer()方法作为处理函数: timer.addEventListener(TimerEvent.TIMER, onTimer); function onTimer(event:TimerEvent):void { trace("on timer"); } Timer 对象不会自动开始,必须调用start()方法启动: timer.start( ); 默认情况下只有调用stop()方法后才会停下来,不过另一种方法是传递给构造器第二个参数作为运行次数,默认值为0即无限次,下面的例子设定定时器运行5次: var timer:Timer = new Timer(1000, 5); //下面的代码设定定时器延时5秒执行deferredMethod()方法: var timer:Timer = new Timer(5000, 1); timer.addEventListener(TimerEvent.TIMER, deferredMethod); timer.start(); XML 是一种结构化的描述数据形式,因其简单,灵活,尤其是在数据交换和可移植等优点现已成为事实上的工业标准。 我们在使用ActionScript过程中,XML是经常碰到的, XML已经成为ActionScript重要组成部分。 ActionScript 3.0 新增了新的操作XML的语法,即 ECMAScriptforXML,也叫E4X,提供一种比 Document Object Model (DOM)更简单更容易访问XML的新方式。使用E4X,你会发现操作XML 比以前更简单了,另外如果你是头一次操作XML,那么E4X也是很容易学习的。 (1)创建XML对象 在ActionScript很多地方都会用到XML对象,可以使用下列几种方式创建XML对象: Ø 创建XML对象并直接用XML进行赋值; var example:XML = 这是E4X表达式的例子,注意等号右边没有引号,ActionScript编译器知道右边的表达式就是XML。上面的XML表达式是静态的,现在看一下如何创建动态的 XML,在XML表达式中可以使用和引入变量。例如要创建一个包含用户名和分数的XML发送到服务端,可以这样: // 创建两个变量 var username:String = "Darron"; var score:int = 1000; var example:XML = ; Ø 传递XML字符串给XML构造函数 var str:String = " var example:XML = new XML( str ); Ø 创建一个空的XML对象并使用E4X填充数据 在日常工作中经常碰到往XML对象里添加新节点,然后把XML传递给其他应用程序。用E4X语 法添加新节点是非常简单的,只要用操作符( .),跟一般的对象属性操作基本类似,看下面的 例子: // 创建一个XML实例 var example:XML = // 创建新的节点 example.newElement = /* 显示: */ trace( example ); 上面的代码中,通过newElement属性来添加新的元素,属性名和内容不一定要相同,如下面的 例子: var example:XML = example.emptyElement = ""; /* 显示: */ trace( example ); 除了用(.)运算符外还可以用([ ]), 如 : var example:XML = var id:int = 10; example[ "user" + id ] = ""; /* 显示: */ trace( example ); 两种写法基本上通用,不过还是有区别的,如下面的例子编译器就会报错: example.some-element = ""; //编译错误 这种情况下只能用[]来设置属性名了: example[ "some-element" ] = ""; 还有个问题需要注意,这种方法增加的节点都是添加在XML树的尾部,要解决这个问题,可用 insertChildBefore()和insertChildAfter() 方法来控制插入的位置。insertChildBefore() 方法在当前元素位置前插入新元素,而insertChildAfter() 在当前元素的后面插入,看下面的例子: var example:XML = example.two = ""; example = example.insertChildBefore( example.two, example = example.insertChildAfter( example.two, /* 显示: */ trace( example ); 要注意的是这两个方法不是修改原来的 XML,而是返回新的 XML 实例。 Ø 添加文本节点 可使用 E4X语法创建文本节点并插入到 XML树中,也可用appendChild( ), prependChild(), insertChildAfter(), 和insertChildBefore() 方法进行更多控制,灵活插入。 // 创建XML实例 var example:XML = example.firstname = "Darron"; example.number = 24.9; example.boolean = true; example.abc = ["a", undefined, "b", "c", null, 7, false]; /* 显示: */ trace( example ); 这个例子同时添加了文本和元素节点,=号右边的值即作为左右元素节点的子文本节点。 要想进行更多的控制可使用 appendChild( ), prependChild( ), insertChildBefore( ), 或者insertChildAfter()。 var example:XML = // 添加名为 two 元素以及值为2的文本子节点 example.appendChild( // 在当前节点前面插入one 元素 example.prependChild( // 在当前节点后面插入 example.insertChildAfter( example.one[0], 1.5 ); //在指定节点前插入 example.insertChildBefore( example.two[0], /* 显示: 1.5 */ trace( example ); 上面的例子代码既加入了元素节点( Ø 创建空的对象,从外部读取XML数据 使用URLLoader.load() 方法且设置dataFormat属性为DataFormat.TEXT读取数据,通过complete事件处理函数转换载入的数据为XML实例。 读取XML文件的步骤如下:首先创建URLLoader实例以简单文本形式读取数据,其dataFormat属性必须设置为DataFormat.Text,监听并添加complete事件处理函数,看下面的例子演示: package { import flash.display.*; import flash.events.*; import flash.net.*; import flash.util.*; public class LoadXMLExample extends Sprite { public function LoadXMLExample( ) { var loader:URLLoader = new URLLoader( ); loader.dataFormat = DataFormat.TEXT; loader.addEventListener( Event.COMPLETE, handleComplete ); loader.load( new URLRequest( "example.xml" ) ); } private function handleComplete( event:Event ):void { try { var example:XML = new XML( event.target.data ); trace( example ); } catch ( e:TypeError ) { trace( "Could not parse text into XML" ); trace( e.message ); } } } } 上面的例子中之所以用try...catch 块,是考虑到读取的数据有可能不是XML格式数据,TypeError 异常就是不能成功转换为 XML 实例时抛出的。 (2)读取XML树中的元素 E4X提供了一个很方便的elements() 方法,该方法返回所有XML对象的子元素节点,再通过foreach 循环即可访问整个XML树结构: var menu:XML = 1.3 MXML和Actionscript
1.3.1 MXML和ActionScript简介
[Flash Builder 安装路径]\sdks\[Flex 版本号]\frameworks\projects\framework\src1.3.2 在MXML中调用ActionScript
// myFunction.as1.3.3 自定义组件
1.4 容器和布局
1.4.1 Application
1.4.2 Panel
1.3.4 Group
1.3.5 Hgroup
1.3.6 VGroup
1.3.7 Scroller
1.3.8 Form 表单布局
实训任务1:Flex应用程序的创建
实训任务2:实现简单的文本编辑器
实训任务3:实现图片浏览器
实训任务4:完善登陆表单
第2章 ActionScript3.0基础
2.1 ActionScript3.0概述
2.2 数据类型和数据运算
2.2.1 数据类型
2.2.2 字符串
2.2.3 数字计算
2.2.4 数字类型的转换
2.2.5 数组的使用
2.2.6 ArrayCollection数组集合
2.3 控制程序的流程
2.3.1 选择语句
2.3.2 循环语句
2.4 ActionScript 3.0面向对象语法
2.4.1 创建类和对象
2.4.2 定义方法
2.4.3 继承
2.4.4 接口
2.4.5 异常处理
2.5 ActionScript3.0常用类
2.5.1 时间和日期
2.5.2 使用AS3.0操作XML
This is a text node
;
for each ( var element:XML in menu.elements() ) {
/* 显示: File*/
trace( element.@label );}
从上面的例子中我们看到elements() 方法只返回下一级的子元素节点,这里面不包括文本节点 和下一级节点,要向访问整个XML结构,还需进行递归循环处理:
walk( menu );
function walk( node:XML ):void {
for each ( var element:XML in node.elements() ) {
walk( element );
}
}
(3)通过名字查找元素节点
直接使用 E4X 的 . 加上属性名语法来查找元素
var fruit:XML =
// 显示: Apple
trace( fruit.name );
就是这么简单,用点操作符(.)即可,再看一下更复杂点的例子:
var author:XML =
// 显示: Darron
trace( author.name.firstName );
还有种简便的方法,即使用双点操作符(..)来跳过一级访问,如:
var author:XML =
// 显示: Darron
trace( author..firstName );
当有多个元素节点具有相同名称时,可通过索引值访问,这有点像数组,使用中括号,根据索 引值访问指定的元素节点,例如:
var items:XML =
;
// 显示: Apple
trace( items.item[0].name );
// 显示: Orange
trace( items.item[1].name );
items.item 返回两个元素的 XMLList 对象,第一个元素的索引值为0,第 二 个 为 1,用 length() 方 法可得到找到的元素节点个数:
// 显示: 2
trace( items.item.length() );
如果想访问特定名称的元素节点,但又不知道有多少个,可用 foreach 循环遍历:
var items:XML =
;
// 使用双点操作符
for each ( var name:XML in items..name ) {
/* 显示: Apple
Orange*/
trace( name );
}
也可用[]操作符来访问:
var nodeName:String = "color";
var fruit:XML =
// Displays: red
trace( fruit[nodeName] );
需要注意的是[]操作符不能和双点操作符一起用
trace( fruit..[nodeName] ); // 导致编译错误
(3)读取文本节点
使用E4X语法,或者用text()方法返回元素的文本节点的XMLList对象,再用toString()方法把文本节点转换为字符串,也可通过int() 或 Number() 将其转换为其他类型。比如下面的xml内容:
根节点为
var book:XML =
;
// 用E4X 语法访问title元素
var title:String = book.title.toString();
// 显示: ActionScript 3.0
trace( title );
另外可通过Boolean(),int()等函数转换文本节点数据类型:
var example:XML =
;
var bool:Boolean = Boolean( example.bool );
var integer:int = int( example.integer );
var number:Number = example.number;
/* 显示:
true
12
9
*/
trace( bool );
trace( integer );
trace( number );
上面的代码有个小小的问题,即 Boolean() 转换可能会不成功,如果
var bool:Boolean = example.bool.toLowerCase() == "true";
再看一下面的例子,这个XML的根节点即包含元素节点也包含文本节点,如果想显示
var fruit:XML =
;
var value:String = fruit.toString();
/* 显示:
*/
trace( value );
这种情况下,用text() 方法可正确返回文本节点内容了:
var fruit:XML =
;
for each ( var textNode:XML in fruit.text() ) {
// 显示: An apple a day...
trace( textNode );
}
(4)删除元素,文本节点和属性
上面几节我们学习了如何添加元素,文本节点和属性到XML对象上。现在我们讨论如何删除这些节点,秘密就在于delete 关键字,
使用 delete 关键字例子:
var example:XML =
;
// 删除fruit元素的color属性
delete example.fruit.@color;
// 删除dairy元素
delete example.dairy;
// 删除vegetable元素的文本节点
delete example.vegetable.text( )[0];
/* 显示:
*/
trace( example );
delete只能一次删除一个节点,如果要删除多个节点,可通过for循环进行删除:
var example:XML =
;
var attributes:XMLList = example.fruit.@*;
for ( var i:int = attributes.length() - 1; i >= 0; i-- ) {
delete attributes[i];
}
/* 显示:
*/
trace( example );
Flash Player关于控制运行时环境提供了更多的信息。The flash.system.Capabilities 类有许多静态方法返回关于播放器和计算机的信息,比如操作系统,语言,音频和视频。还有其他的类如 flash.display.Stage和 flash.system.Security控制其他一些元素如播放器右键菜单和设置对话框。flash.display.Stage 类也控制影片剪辑缩放和对齐。
(1)检测播放器版本
检测客户机上的Flash版本是个多年以来的难题,有各种开发者提供的方法,一般有三种方法:
Ø 基于浏览器脚本检测
Ø 服务端检测
Ø ActionScript 检测
第一种方法使用JavaScript 或 VBScript 检测Flash 播放器版本。但是很多脚本在不同的平台不同的浏览器上会有兼容性问题出现。
服务端检测也有局限性,如果你无权限创建服务端脚本,这就很困难了。
大多基于 ActionScript 的检测技术不能在ActionScript 3.0 上用了。 ActionScript 3.0 有一套自己 的检测客户端版本的方法,那就是flash.system.Capabilities.version 属性。但是它不能检测Flash Player 8.5之前的版本。
还好Adobe 已经考虑到所有这些问题,推出了 Flash Player Detection Kit(http://www.adobe.com/software/flashplayer/download/detection_kit) 来指导你用最好的办法检测播放器版本。
检测包里包含文档和各种解决办法,包括VBScript 和 JavaScript 例子;ActionScript 检测;还有服务端的ColdFusion和PHP 脚本检测。
基于ActionScript的检测是比较好的,它可以支持到Flash播放器4,它使用一个 Flash 4 .swft来 检测当前版本,你所要做的就是在脚本里设置最小的版本变量,如果当前版本高,它会调用指定的内容。
(2)检测操作系统
ActionScript 3.0中,flash.system.Capabilities.os 属性返回操作系统名称和版本字符串。值可能包 括Windows XP, Windows 2000, Windows NT, Windows 98/Me, Windows 95, 和 Windows CE. 在苹 果机上,字符串包括版本号,比如 Mac OS 9.2.1 或 Mac OS X 10.4.4.
你可能基于操作系统做一些特殊处理,比如,根据当前系统载入特定的图标,或只是记录下用 户的操作系统来统计。
下面的代码展示检测操作系统:
var os:String = System.capabilities.os.substr(0, 3);
if (os == "Win") {
} else if (os == "Mac") {
} else {
}
(3)检测播放器类型
播放器的类型有:
Ø 浏览器插件形式存在于 Mozilla 或 Firefox
Ø ActiveX 控件形式存在于Internet Explorer
Ø 独立播放器
Ø 外部播放器,它与Flash IDE进行交互。
这些都是.swf 运行的环境,如果你要使用脚本进行交互,这就需要知道应用程序到底在Internet Explorer或其他的浏览器运行。如果在独立播放器里运行,那么JavaScript等脚本就不管用了。
检 测 播 放 器 类 型 , 可以察看 flash.system.Capabilities.playerType的值 。 它可能是 PlugIn, ActiveX, StandAlone和 External:
使用 flash.system.Capabilities.playerType 属性:
if(flash.system.Capabilities.playerType == "Plugin") {
// do actions for Mozilla, etc. browsers
}
else if(flash.system.Capabilities.playerType == "ActiveX") {
// do actions for IE
}else {
// do actions for no browser
}
(4)检测系统语言
flash.system.Capabilities.language 属性给出客户端系统的语言,返回两个 ISO-639-1 字符(如 "fr" 代表 French). 有些国家代码两个字符是不合适的,比如( "zh-CN" 代表 Simplified Chinese 和 "zh-TW" 代表 Traditional Chinese).
下面的代码展示如何使用语言属性:
trace(flash.system.Capabilities.language);
var greetings:Array = new Array();
greetings["en"] = "Hello";
greetings["es"] = "Hola";
greetings["fr"] = "Bonjour";
var lang:String = flash.system.Capabilities.language.substr(0, 2);
if (greetings[lang] == undefined) {
lang = "en";}
trace(greetings[lang]);
如果要创建国际化的Flash,可以把文本保存在数组里,根据语言动态显示,或者直接做成多个Flash版本(每个语言一个),如 myMovie_en.swf, myMovie_es.swf, myMovie_fr.swf, 等.
//从 capabilities 对象上得到语言值
var lang:String = System.capabilities.language.substr(0, 2);
// 创建支持语言数组
var supportedLanguages:Array = ["en", "es", "fr"];
// 设置默认语言.
var useLang:String = "en";
//循环匹配,如果找到,设置 useLang
for (var i:int = 0; i < supportedLanguages.length; i++) {
if (supportedLanguages[i] == lang) {
useLang = lang;
break;
}
}
// 载入对应Flash
var movieURL:String = "myMovie_" + useLang + ".swf");
还有一点也很重要,比如用户使用的输入语言,比如中文,日文,韩文,输入这些字符需要输入法,这时特定操作系统的一部分。
为了检测用户使用什么输入法 ,flash.system.Capabilities.hasIME 返回 true 或 false ,flash.system.IME类返回关于输入法的信息。flash.system.IME.enabled属性设置用户是否可以使用输入法。在有些操作系统和版本上你可以发送字符串给 IME 来转换成正确的字符,接受 IME 的返回,但这不是所有操作系统都支持的,最好检测下先。
(5)检测显示设置
使用 system.capabilities 对象的 screenResolutionX 和 screenResolutionY 属性可以知道客户机的显示设置情况
screenResolutionX 和 screenResolutionY 属性返回桌面的显示分辨率:
trace(flash.system.Capabilities.screenResolutionX);
trace(flash.system.Capabilities.screenResolutionY);
// 1024
// 768
有了这些值,你可以决定怎样显示flash影片。这一点对于Flash播放器也是很重要的,例如,手机屏幕和电脑屏幕尺寸是不同的,因此你要根据情况载入不同的尺寸的内容。
var resX:int = flash.system.Capabilities.screenResolutionX;
var resY:int = flash.system.Capabilities.screenResolutionY;
if ( (resX <= 240) && (resY <= 320) ) {
var url:String = "main_pocketPC.swf";
}else {
var url:String = "main_desktop.swf";
}
loader.load(new URLRequest(url));
利用分辨率还可以居中你的弹出窗口:
var resX:int = flash.system.Capabilities.screenResolutionX;
var resY:int = flash.system.Capabilities.screenResolutionY;
//设置窗口的宽和高
var winW:int = 200;
var winH:int = 200;
// 设置窗口起始坐标
var winX:int = (resX / 2) - (winW / 2);
var winY:int = (resY / 2) - (winH / 2);
// 创建代码,然后传递给 URLLoader.load( )
// 打开新浏览器窗口
var jsCode:String = "javascript:void( newWin=window.open('http://www.person13.com/'," + "'newWindow', 'width=" + winW +
", height=" + winH + "," +"left=" + winX + ",top=" + winY + "'));";
// 使用 URLLoader 对象调用 JavaScript 函数
urlLoader.load(new URLRequest(jsCode));
另外,得到屏幕分辨率可以确定是否缩放 Flash 影片。例如,用户把屏幕分辨率调高了,这时字体就变得小了。
(6)缩放影片
使用 stage.scaleMode 属性可以让影片适应屏幕大小。
这里有几种缩放模式:exactFit, noBorder, noScale, 和 showAll。为了避免编写上错误,这些字符串都成为了 flash.display.StageScaleMode类的静态属性:EXACT_FIT, NO_BORDER, NO_SCALE, 和 SHOW_ALL。
Flash 播放器默认的缩放模式是showAll。这种模式会按照影片原始比例进行缩放以适应播放器大小。这样如果播放器的比例和影片的比例不一致就会导致电影边框的出现。设置应用程序的缩放模式:
stage.scaleMode = StageScaleMode.SHOW_ALL;
注意到 stage 并不是个全局对象,但是它是任何可视化对象的一个属性,因此这个语句在sprite类或继承自DisplayObject类里都可以。
noBorder 模式在保持原始比例下进行缩放以适应播放器,但是,如果播放器和影片比例不匹配 ,影片显示不下的会被剪切掉,使用下面的语句设置:
stage.scaleMode = StageScaleMode.NO_BORDER;
exactFit 模式缩放影片适应播放器,它改变了电影原始比例,如果必要,它会匹配播放器,这样电影总是填充整个播放器,但是这样电影中的元素可能会扭曲,代码如下:
stage.scaleMode = StageScaleMode.EXACT_FIT;
noScale 模式即不进行缩放,保持原始比例。使用该模式不要忘了设置对齐方式。
stage.scaleMode = StageScaleMode.NO_SCALE;
(7)改变对齐方式
默认下 Flash 电影会居中显示。可以利用任何可视化对象的 stage.align 属性来重新设置电影的对齐方式。
这里没有水平和垂直都居中的模式,其实,默认模式就是它了,但如果你改变了对齐方式又想回到默认模式这时后只能传递空字符串""。
下面的类展示了缩放和对齐效果:
package {
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
public class ExampleApplication extends Sprite {
public function ExampleApplication() {
stage.scaleMode=StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_RIGHT;
graphics.beginFill(0xff0000);
graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
graphics.endFill();
}
}
}
(8)隐藏Flash播放器的菜单项
AS3.0不能够完全改变Flash播放器的右键弹出菜单,但是可以设置stage.showDefaultContextMenu 属性 为false来最小化菜单项以禁用右键菜单。
默认下Flash播放器右键弹出菜单的项目有:
Ø Zoom In
Ø Zoom Out
Ø Show All
Ø Quality (Low, Medium, or High)
Ø Settings
Ø Print
Ø Show Redraw Regions (debug 版本)
Ø Debugger (debug 版本)
通过下面的语句可以移除许多项目,Settings和About是不能移除的: stage.showDefaultContextMenu = false;
遗憾的是,Flash没有提供方法完全禁用右键菜单。
(8)检测设备音频
如果用户系统有播放音频的能力,则 flash.system.Capabilities.hasAudio 属性就返回True 。这实际上很重要,如果目标设备不支持音频,那就要避免强制用户下载音频内容(因此音频内容都比较大)。
// 只有当播放器可以播放声音才加入包含声音的.swf
if (flash.system.Capabilities.hasAudio) {
content = "sound.swf";
} else {
content = "silent.swf";
}
即时系统有播放音频能力也不意味着它有播放 mp3的能力。因此当发布含有 mp3内容时应用flash.system.Capabilities.hasMP3 属性检测下目标设备。
if (flash.system.Capabilities.hasMP3) {
var url:URLRequest = new URLRequest("sound.mp3");
sound = new Sound(url);
sound.play();
} else {
}
(10)检测设备视频
检测用户端是否能播放视频也同样重要,使用flash.system.Capabilities.hasStreamingVideo 属性检测是否能播放视频流。如果返回 false,就可以让用户下载内嵌视频的.swf文件,在这之前也要用 flash.system.Capabilities.hasEbeddedVideo 确定,
看下面的代码:
if(flash.system.Capabilities.hasStreamingVideo) {
// 播放视频流
}else if(
flash.system.Capabilities.hasEmbeddedVideo) {
// 下载内嵌视频的swf文件
}
else {
//
}
如果应用程序需要视频流编码,比如传送摄像机视频流,还要确定系统是否具有编码能力,使用flash.system.Capabilities.hasVideoEncoder 属性检测。
(11)提示用户改变播放器设置
flash.system.Security.showSettings() 方法打开播放器设置对话框,它包含多个标签,也可以调用 该方法时传递参数给它直接打开相应标签,该参数字符串是 flash.system.SecurityPanel 类的静 态属性:
Ø SecurityPanel.CAMERA 摄像机面板
Ø SecurityPanel.DEFAULT 默认面板
Ø SecurityPanel.LOCAL_STORAGE 本地存储面板
Ø SecurityPanel.MICROPHONE 话筒面板
Ø SecurityPanel.PRIVACY 安全控制面板
Ø SecurityPanel.SETTINGS_MANAGER 设置管理面板会打开浏览器进行更多设置
如果没有传递参数,默认使用 SecurityPanel.DEFAULT. 下面的例子打开本地存储面板:
flash.system.Security.showSettings(SecurityPanel.LOCAL_STORAGE);
任务实训部分
训练技能点
Ø 事件处理。
Ø 常用控件
Ø As基本语法
Ø 产生随机数
需求说明
实现随机产生N注的双色球号码。其中,双色球抽奖方法是每注号码,由六个红球号码和一个蓝球号码组成,红球从1~33中产生,蓝球从1~16中产生。
实现思路
(1)创建MXML应用程序,并设计功能接界面。
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
(2)为开始按钮添加事件处理代码 修改过后的代码如下。
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
protected function button1_clickHandler(event:MouseEvent):void { //清空之前的运行结果 this.lbl.text=""; //获取到产生的双色球注数。 var quantity:int =int( this.quantityInput.text); this.bar.minimum=0; this.bar.maximum=quantity; for(var v:uint=0;v<=quantity;v++){ //保存一注红色球号码,此处不考虑重复。 var redticket :String=''; for(var i:uint=0;i<=6;i++){ var n:int = Math.random()*32+1; if(n<10){ redticket+='0'+n.toString()+' '; } else{ redticket+=n.toString()+" "; } } //保存一注蓝色球号码 var blueticket:int=Math.random()*15+1; if(blueticket<10){ this.lbl.text+=redticket+'0'+blueticket+'\n'; } else{ this.lbl.text+=redticket+blueticket+'\n'; } //更新进度条 this.bar.setProgress(v,quantity); } } ]]>
(3) 运行程序,效果如图2.2.1所示。
图2.2.1 双色球产生器
训练技能点
Ø 获得系统日期的方法
Ø 日期的格式化
Ø 定时器的使用
需求说明
在AS代码中使用Date对象获取当前时间的完整信息,,制作一个实时显示时间信息的时钟。
实现思路:
(1) 创建程序主界面,并设置creationComplete事件,在程序开始运行的时候自动显示时间。
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="application1_creationCompleteHandler(event)" minWidth="955" minHeight="600 >
protected function application1_creationCompleteHandler(event:FlexEvent):void { } ]]>
(2) 在creationComplete事件处理方法中创建定时器 每一秒钟运行一次 更新时间。
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="application1_creationCompleteHandler(event)" minWidth="955" minHeight="600" backgroundColor="#FFFFFF">
import mx.events.FlexEvent; import mx.formatters.DateFormatter; protected function application1_creationCompleteHandler(event:FlexEvent):void { var timer :Timer= new Timer(1000); timer.addEventListener(TimerEvent.TIMER,onTimer); timer.start(); } protected function onTimer(event:TimerEvent):void{ var date:Date = new Date(); var df:DateFormatter = new DateFormatter(); df.formatString="YYYY-MM-DD 星期E HH:NN:SS"; this.dateLbl.text=df.format(date); } ]]>
(3) 运行程序,效果如图2.2.2所示。
图2.2.2 时钟
训练技能点
Ø 使用String对象的split方法将字符串分割为数组
Ø 使用String对象的replace方法实现字符串替换
Ø 使用RegExp对象实现全局检索
Ø 使用innerHTML获取和设置对象内部HTML文本
需求说明
编写程序,使用“*”号替换论坛中禁止出现的词汇。。
实现思路:
(1) 使用字符串对象定义论坛禁语,用逗号隔开,如“恶心,白痴”。
(2) 使用String对象的split方法将论坛禁语分割为数组形式。
(3) 遍历步骤(2)中得到的数组中的禁语字符串,在循环中将数组中的禁语字符串依次设置为RegExp对象。:
(4) 使用String对象的replace方法实现替换。
(5) 参考代码如下。
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
import mx.controls.Alert; var str:String="白痴,笨蛋"; protected function button1_clickHandler(event:MouseEvent):void { var keyWords:Array=str.split(","); var replay:String=this.ta2.text; for each(var key in keyWords){ var reg:RegExp = new RegExp(key,"gi"); replay=replay.replace(reg,"**"); } this.ta1.text+="您发表了评论:\n"+replay+"\n"; } ]]>
(6) 运行程序 效果如图2.2.3所示。
图2.2.3 替换论谈禁语
训练技能点
使用E4X技术操作XML
需求说明
编写程序,从XML文件中读取数据显示在表格中,填写学员资料后,点击添加即可在表格中显示新的数据,选中一行数据,点击删除按钮即可从表格中删除。
实现思路:
(1)在SRC下准备一个students.xml文件。
(2)构建程序主界面。
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="application1_creationCompleteHandler(event)" minWidth="955" minHeight="600">
import mx.events.FlexEvent; protected function application1_creationCompleteHandler(event:FlexEvent):void { } ]]>
(3)在creationComplete事件处理方法中,读取xml并显示在表格中,并实现添加 删除功能。
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="application1_creationCompleteHandler(event)" minWidth="955" minHeight="600">
import mx.controls.Alert; import mx.events.FlexEvent; private var xml:XML; protected function application1_creationCompleteHandler(event:FlexEvent):void { var loader:URLLoader = new URLLoader(); loader.dataFormat =URLLoaderDataFormat.TEXT; Alert.show(URLLoaderDataFormat.TEXT+''); loader.addEventListener( Event.COMPLETE, handleComplete ); loader.load( new URLRequest( "students.xml" ) ); } private function handleComplete( event:Event ):void { try { xml = new XML( event.target.data ); this.adg1.dataProvider=xml.student; } catch ( e:TypeError ) { trace( "Could not parse text into XML" ); trace( e.message ); } } protected function button1_clickHandler(event:MouseEvent):void { xml.newElement = ; this.adg1.dataProvider=xml.student; } protected function button2_clickHandler(event:MouseEvent):void { var id:String = this.adg1.selectedItem.stuid; var students:XMLList = xml.student; for ( var i:int = students.length()- 1; i >= 0; i-- ) { if(id== students[i].stuid){ delete students[i]; } } this.adg1.dataProvider=xml.student; } ]]>
(4)运行程序 效果如图2.2.4所示。
图2.2.4 E4X操作XML
巩固练习
选择题
1. 不属于AS数值类型的是 ()
A. int。
B. uint。
C. double。
D. Number。
2. 关于AS的数据类型说法,正确的是 ()
A. Object是所有AS类型的基类。
B. Number类型的默认值是0。
C. AS中Function也是一种数据类型。
D. “*”(变体类型)的含义是变量的类型不确定。
3. AS类的合法修饰符是()。
A. public。
B. intemal。
C. dynamic。
D. default。
4. Flex中使用XML,说法错误的是()。
A. 创建XML可以使用 var example:XML = “
B. 可以通过newElement属性来为XML添加新的元素。
C. 使用URLLoader加载XML文档的时候必须将其dataFormat 属 性设置为XML。
D. E4X提供了一个很方便的elements() 方法,该方法返回所有XML对象的子元素节点,再通过foreach 循环即可访问整个XML树结构。