注明:本实例代码出自《Flex 从入门到精通》 聂晓霞编著,对教材代码略有修改以便适用于Flex4版本。
实例为查询天气预报的系统,基于Cairngorm框架结构,远程调用一个公用的Web Services网站的数据,将信息以数据和图标显示出来。对于Cairngorm应用框架,分为四大模块(模型、视图、控制、服务),对于其内在的原理便不再赘述,下图可清晰分析其工作方式:
本实例的文件和程序流程图如下图,可方便了解项目的整体布局和执行过程:
在myeclipes中建立的flex项目文件结构如下:
CityInfoVO.as:
package com.weather.example.vo
//定义返回的城市信息所使用的值对象
{
import com.adobe.cairngorm.vo.ValueObject;
[Bindable]
public class CityInfoVO implements ValueObject
{
public var cityName :String = ""; //返回结果的城市名
public var stateName :String = ""; //返回结果的州名
public var latitude :String = ""; //返回结果纬度
public var longitude :String = ""; //返回结果经度
public var zipcode :String = ""; //返回结果邮编
}
}
QueryItemVO.as
package com.weather.example.vo
//定义查询数值使用的值对象
{
import com.adobe.cairngorm.vo.ValueObject;
[Bindable]
public class QueryItemVO implements ValueObject
{
public var cityname:String = ""; //查询城市名
public var zipcode:String = ""; //查询邮政编码
}
}
CityInfoPanel.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:view="com.weather.example.view.*"
horizontalCenter="center">
<s:layout>
<s:BasicLayout/>
</s:layout>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.adobe.cairngorm.control.CairngormEventDispatcher;
import com.weather.example.event.GetWeatherByCityEvent;
import com.weather.example.model.ModelLocator;
import com.weather.example.vo.*;
//使用模型定位器来绑定结果信息到用户界面上
[Bindable]
public var model:ModelLocator = ModelLocator.getInstance();
]]>
</fx:Script>
<mx:Form id="loginForm">
<mx:FormItem label="城市名称:">
<s:TextInput id="cityname" minWidth="100" text="{model.getWeather.cityInfoVO.cityName}"/>
</mx:FormItem>
<mx:FormItem label="州名:">
<s:TextInput id="statename" minWidth="100" text="{model.getWeather.cityInfoVO.stateName}"/>
</mx:FormItem>
<mx:FormItem label="邮编:">
<s:TextInput id="zipcode" minWidth="100" text="{model.getWeather.cityInfoVO.zipcode}"/>
</mx:FormItem>
<mx:FormItem label="纬度:">
<s:TextInput id="latitude" minWidth="100" text="{model.getWeather.cityInfoVO.latitude}"/>
</mx:FormItem>
<mx:FormItem label="经度:">
<s:TextInput id="longitude" minWidth="100" text="{model.getWeather.cityInfoVO.longitude}"/>
</mx:FormItem>
</mx:Form>
</s:Panel>
QueryPanel.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:view="com.weather.example.view"
title="输入咨询信息"
horizontalCenter="center" width="254" height="251">
<s:layout>
<s:BasicLayout/>
</s:layout>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.adobe.cairngorm.control.CairngormEventDispatcher;
import com.weather.example.event.GetWeatherByCityEvent;
import com.weather.example.model.ModelLocator;
import com.weather.example.vo.QueryItemVO;
[Bindable]
private var model:ModelLocator = ModelLocator.getInstance();
//查询天气函数
public function queryWeather():void{
var queryItemVO:QueryItemVO = new QueryItemVO();
queryItemVO.cityname = cityname.text;
queryItemVO.zipcode = zipcode.text;
model.getWeather.queryItemVO = queryItemVO;
var event:GetWeatherByCityEvent = new GetWeatherByCityEvent(queryItemVO);
CairngormEventDispatcher.getInstance().dispatchEvent(event);
}
//清除输入信息的函数
private function clear():void{
cityname.text = "";
zipcode.text = "";
}
]]>
</fx:Script>
<mx:Text text="请填写其中一项查询数据,如果输入两项参数,查询以邮编为主" color="#1261CD" width="180" height="50" x="39" y="1"/>
<mx:Form id="loginForm" x="10" y="53" height="91">
<!--输入城市名称的文本输入框-->
<mx:FormItem label="城市名称:">
<s:TextInput minWidth="100" id="cityname" enter="queryWeather()"/>
</mx:FormItem>
<!--邮编输入框-->
<mx:FormItem label="邮编:">
<s:TextInput minWidth="100" id="zipcode" enter="queryWeather()"/>
</mx:FormItem>
</mx:Form>
<s:Label text="{model.getWeather.statusMessage}" color="#CD2812"/>
<!--控制按钮触发查询和清除的函数-->
<mx:ControlBar horizontalAlign="right" x="55" y="148" width="174" height="51">
<s:Button label="清空" click="clear()"/>
<s:Button label="查询" enabled="{!model.getWeather.isPending}" click="queryWeather()"/>
</mx:ControlBar>
</s:Panel>
WeatherResultChart.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300">
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.weather.example.model.ModelLocator;
[Bindable]
public var model :ModelLocator = ModelLocator.getInstance();
]]>
</fx:Script>
<!--使用折线图显示温度曲线信息-->
<mx:LineChart id="myChart" dataProvider="{model.getWeather.TemperatureList}"
showDataTips="true" width="100%" height="100%">
<!--X坐标的数据序列-->
<mx:horizontalAxis>
<mx:CategoryAxis dataProvider="{model.getWeather.TemperatureList}"
categoryField="Day"/>
</mx:horizontalAxis>
<!--Y坐标的数据序列-->
<mx:series>
<mx:LineSeries yField="MaxTemperatureC" displayName="最高摄氏温度"/>
<mx:LineSeries yField="MinTemperatureC" displayName="最低摄氏温度"/>
<mx:LineSeries yField="MaxTemperatureF" displayName="最高华氏温度"/>
<mx:LineSeries yField="MinTemperatureF" displayName="最低华氏温度"/>
</mx:series>
</mx:LineChart>
<!--Legend的数据源-->
<mx:Legend dataProvider="{myChart}"/>
</mx:VBox>
WeatherResultPanel.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300">
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.weather.example.model.ModelLocator;
[Bindable]
public var model :ModelLocator = ModelLocator.getInstance();
]]>
</fx:Script>
<!--使用AdvancedDataGrid显示信息-->
<mx:AdvancedDataGrid dataProvider="{model.getWeather.weatherDataList}" variableRowHeight="true"
width="100%" height="100%">
<!--使用AdvancedDataGrid的groupeColumns功能来显示不同单位的温度-->
<mx:groupedColumns>
<mx:AdvancedDataGridColumn headerText="日期" dataField="Day" width="200"/>
<!--使用条目渲染器显示天气图标-->
<mx:AdvancedDataGridColumn headerText="天气">
<mx:itemRenderer>
<fx:Component>
<mx:HBox horizontalAlign="left"
paddingLeft="30" paddingRight="0"
verticalAlign="middle" horizontalScrollPolicy="off">
<mx:Image source="{data.WeatherImage}"/>
</mx:HBox>
</fx:Component>
</mx:itemRenderer>
</mx:AdvancedDataGridColumn>
<!--使用高级数据栅格的ColumnGroup来显示摄氏和华氏不同单位的最高温度-->
<mx:AdvancedDataGridColumnGroup headerText="最高温度">
<mx:AdvancedDataGridColumn headerText="摄氏" dataField="MaxTemperatureC"/>
<mx:AdvancedDataGridColumn headerText="华氏" dataField="MaxTemperatureF"/>
</mx:AdvancedDataGridColumnGroup>
<!--使用高级数据栅格的ColumnGroup来显示摄氏和华氏不同单位的最低温度-->
<mx:AdvancedDataGridColumnGroup headerText="最低温度">
<mx:AdvancedDataGridColumn headerText="摄氏" dataField="MinTemperatureC"/>
<mx:AdvancedDataGridColumn headerText="华氏" dataField="MinTemperatureF"/>
</mx:AdvancedDataGridColumnGroup>
</mx:groupedColumns>
</mx:AdvancedDataGrid>
</mx:Canvas>
GetWeather.as
package com.weather.example.model
//具体的数据服务
{
import com.weather.example.vo.*;
import mx.collections.ArrayCollection;
public class GetWeather
{
//查询信息对象
[Bindable]
public var queryItemVO :QueryItemVO = new QueryItemVO();
//城市信息对象
[Bindable]
public var cityInfoVO :CityInfoVO = new CityInfoVO();
//当前状态信息
[Bindable]
public var statusMessage :String = "";
//是否查询按钮被激活或禁用
[Bindable]
public var isPending :Boolean = false;
//城市信息数组集合
[Bindable]
public var cityDataList:ArrayCollection = new ArrayCollection();
//天气信息数组集合
[Bindable]
public var weatherDataList:ArrayCollection = new ArrayCollection();
//温度信息数组集合
[Bindable]
public var TemperatureList:ArrayCollection = new ArrayCollection();
}
}
ModelLocator.as
package com.weather.example.model
{
import com.adobe.cairngorm.model.ModelLocator;
[Bindable]
public class ModelLocator implements com.adobe.cairngorm.model.ModelLocator
{
private static var modelLocator :com.weather.example.model.ModelLocator;
//定义Instance 模型定位器
public static function getInstance():com.weather.example.model.ModelLocator{
if(modelLocator == null)
modelLocator = new com.weather.example.model.ModelLocator();
return modelLocator;
}
public function ModelLocator()
{
if(com.weather.example.model.ModelLocator.modelLocator!=null)
throw new Error("Only one ModelLocator Instance shoule be instantiated");
}
//定义定位器中的变量
public var getWeather:GetWeather = new GetWeather();
}
}
GetWeatherByCityEvent.as
package com.weather.example.event
{
import com.adobe.cairngorm.control.CairngormEvent;
import com.weather.example.vo.QueryItemVO;
import com.weather.example.control.GetWeatherByCityControl;
public class GetWeatherByCityEvent extends CairngormEvent
{
public var queryItemVO:QueryItemVO;
public function GetWeatherByCityEvent(queryItemVO:QueryItemVO)
{
super(GetWeatherByCityControl.EVENT_QUERY);
this.queryItemVO = queryItemVO;
}
}
}
GetWeatherByCityControl.as
package com.weather.example.control
{
import com.adobe.cairngorm.control.FrontController;
import com.weather.example.commands.GetWeatherByCityCommand;
import com.weather.example.event.GetWeatherByCityEvent;
public class GetWeatherByCityControl extends FrontController
{
public function GetWeatherByCityControl()
{
addCommand(GetWeatherByCityControl.EVENT_QUERY,GetWeatherByCityCommand);
}
public static const EVENT_QUERY:String = "query";
}
}
GetWeatherByCityCommand.as
package com.weather.example.commands
//实现Command 和IResponder 类,具体执行查询命令
//处理业务逻辑,调用Delegates,更新服务定位器中存储的对象和变量
{
import com.adobe.cairngorm.commands.Command;
import com.adobe.cairngorm.control.CairngormEvent;
import com.weather.example.business.ServicesDelegate;
import com.weather.example.event.GetWeatherByCityEvent;
import com.weather.example.model.ModelLocator;
import mx.collections.ArrayCollection;
import mx.rpc.IResponder;
import mx.rpc.events.FaultEvent;
import mx.utils.ObjectProxy;
public class GetWeatherByCityCommand implements Command,IResponder
{
private var model:ModelLocator = ModelLocator.getInstance();
public function execute(event:CairngormEvent):void
{
//调用委托方法
model.getWeather.isPending = true;
var delegate:ServicesDelegate = new ServicesDelegate(this);
var queryEvent:GetWeatherByCityEvent = GetWeatherByCityEvent(event);
delegate.query(queryEvent.queryItemVO);
}
public function result(event:Object):void{
//得到远程结果
var resultAry:Object = Object(event.result);
//处理天气信息
var ary:ArrayCollection = new ArrayCollection();
//判断是否得到了返回结果
if(resultAry.Details==null){//当返回结果为null时,显示相应的提示信息
model.getWeather.statusMessage = "请填写正确的查询信息";
model.getWeather.isPending = false;
}
else{//得到正确的结果
ary = ArrayCollection(resultAry.Details); //将温度数据存储到一个数组集合中
ary.removeItemAt(ary.length - 1); // 去掉最后一个空数据
model.getWeather.weatherDataList = ary; //将天气数据赋值给模型控制器相应的变量
model.getWeather.TemperatureList = new ArrayCollection();
for each(var temp:Object in ary){//获取数组集合中每天的温度值
if(temp!= null){
var obj:ObjectProxy = new ObjectProxy();
obj.Day = temp.Day;
obj.MaxTemperatureC = temp.MaxTemperatureC;
obj.MinTemperatureC = temp.MinTemperatureC;
obj.MaxTemperatureF = temp.MaxTemperatureF;
obj.MinTemperatureF = temp.MinTemperatureF;
model.getWeather.TemperatureList.addItem(obj);
}
}
//将查询的邮编赋值给模型控制器中城市信息的值对象
if(model.getWeather.queryItemVO != null && model.getWeather.queryItemVO.zipcode !=""){
model.getWeather.cityInfoVO.zipcode = model.getWeather.queryItemVO.zipcode;
}
//将获取的结果赋值给模型控制器中城市信息的值对象
model.getWeather.cityInfoVO.cityName = resultAry.PlaceName;
model.getWeather.cityInfoVO.stateName = resultAry.StateCode;
model.getWeather.cityInfoVO.latitude = resultAry.Latitude;
model.getWeather.cityInfoVO.longitude = resultAry.Longitude;
model.getWeather.isPending = false;
}
}
//处理错误结果
public function fault(event:Object):void{
//得到错误信息
var faultEvent:FaultEvent = FaultEvent(event);
model.getWeather.statusMessage = "远程服务错误";
model.getWeather.isPending = false;
}
}
}
ServicesDelegate.as
package com.weather.example.business
{
import com.adobe.cairngorm.business.Responder;
import com.adobe.cairngorm.business.ServiceLocator;
import com.weather.example.model.ModelLocator;
import com.weather.example.vo.QueryItemVO;
import mx.rpc.IResponder;
public class ServicesDelegate
{
private var responder:IResponder;
private var service:Object;
private var model:ModelLocator = ModelLocator.getInstance();
//服务委托
public function ServicesDelegate(responder:IResponder){
this.service = ServiceLocator.getInstance().getWebService("WeatherServices");
this.responder = responder;
}
//查询函数
public function query(queryItemVO:QueryItemVO):void{
if(queryItemVO.zipcode!=""){//如果邮编不为空,则使用邮编来查询
model.getWeather.statusMessage = "";
//调用远程Web Services的GetWeatherByZipCode的操作
var call:Object = service.GetWeatherByZipCode(queryItemVO.zipcode);
call.addResponder(responder);
}
else if(queryItemVO.cityname!=""){//如果邮编为空,使用城市名查询
model.getWeather.statusMessage = "";
var call2:Object = service.GetWeatherByPlaceName(queryItemVO.cityname);
call2.addResponder(responder);
}
else{//如果都为空,显示相应的错误信息
model.getWeather.statusMessage = "请至少填写其中一项查询信息";
model.getWeather.isPending = false;
}
}
}
}
Services.mxml
<?xml version="1.0" encoding="utf-8"?>
<cairngorm:ServiceLocator
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:cairngorm="com.adobe.cairngorm.business.*">
<!--定义web service 的各项参数和方法-->
<mx:WebService id="WeatherServices"
wsdl="http://www.webservicex.net/WeatherForecast.asmx?wsdl"
useProxy="false" showBusyCursor="true">
<mx:operation name="GetWeatherByPlaceName"/>
<mx:operation name="GetWeatherByZipCode"/>
</mx:WebService>
</cairngorm:ServiceLocator>
程序运行结果如图(出现远程服务错误...)
本文版权归作者所有,欢迎转载学习,但需在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。