索引
- 使用Flex+Cairngorm+AIR制作列车时刻表查询工具[连载一]
- 使用Flex+Cairngorm+AIR制作列车时刻表查询工具[连载二]
- 使用Flex+Cairngorm+AIR制作列车时刻表查询工具[连载三]
打开Flex Builder创建一个新项目,命名为“TrainSchedule”。在项目的libs目录中,放入我们要引入的Cairngorm的类库(Cairngorm.swc)。
在src目录中建立一个名为data的文件夹,放入我们要查询的SQLite数据库文件(TrainsInfo.db),这个文件也可以在源码的相应目录找到。
按照MVC的原则,建立如下的几个目录(为了让大家了解这些目录的用途,我特意做了备注):
- control – 用于定义前端控制器
- business – 包含Service和代理(delegate)
- view – 视图和组件
- command – 命令,代码的主要执行部分
- event – 自定义事件
- model – 数据模型
- vo - ValueObject
首先,让我们来完成视图部分的制作,通过分析,我们发现需要3个视图:
- 视图1:搜索界面
- 视图2:搜索结果(按照列车车次检索)界面
- 视图3:搜索结果(按照出发和目的地检索)界面
建立这3个视图文件:
SearchForm.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" horizontalAlign="left" verticalAlign="middle"> <mx:Script> <![CDATA[ import com.example.event.SearchByTrainNameEvent; import com.example.event.SearchByStationEvent; import com.example.model.TrainModelLocator; private var model : TrainModelLocator = TrainModelLocator.getInstance(); private function searchByTrainName():void { var event:SearchByTrainNameEvent = new SearchByTrainNameEvent(); event.trainName = trainNameInput.text; event.dispatch(); } private function searchByStation():void { var event:SearchByStationEvent = new SearchByStationEvent(); event.start = startStation.text; event.end = endStation.text; event.dispatch(); } ]]> </mx:Script> <mx:VBox> <mx:Image source="assets/png-0005.png"/> </mx:VBox> <mx:VRule height="240" alpha="0.15"/> <mx:VBox> <mx:Form> <mx:Label text="按照列车车次查询:" /> <mx:TextInput id="trainNameInput" width="197" text="T585"/> <mx:Button label="查询" click="searchByTrainName()"/> <mx:Label text="按出发地点-目的地查询:" /> <mx:HBox> <mx:TextInput width="81" id="startStation" text="北京"/> <mx:Label text="-" /> <mx:TextInput width="81" id="endStation" text="邯郸"/> </mx:HBox> <mx:Button label="查询" click="searchByStation()"/> <mx:Label text="查询来源" /> <mx:HBox> <mx:RadioButton label="WebService" selected="true" click="model.currentService = 'webService'"/> <mx:RadioButton label="本地数据库" click="model.currentService = 'dataBase'"/> </mx:HBox> </mx:Form> </mx:VBox> </mx:HBox>
SearchResultByStationList.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Box xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" creationComplete="init()"> <mx:Script> <![CDATA[ import com.example.model.TrainModelLocator; import com.example.event.SearchByTrainNameEvent; [Bindable] private var model : TrainModelLocator = TrainModelLocator.getInstance(); private function init():void { // } private function doSearch():void { var event:SearchByTrainNameEvent = new SearchByTrainNameEvent(); event.trainName = dg.selectedItem.TrainCode; event.dispatch(); } ]]> </mx:Script> <mx:HBox width="100%" height="30"> <mx:Label text="{'搜索车站('+model.startStation+'到'+model.arriveStation+')的返回结果:'+model.currentStaionList.trainStationList.length}"/> <mx:Spacer width="100%"/> <mx:Button label="<--返回" click="model.currentState = ''"/> </mx:HBox> <mx:DataGrid id="dg" width="100%" height="100%" dataProvider="{model.currentStaionList.trainStationList}" itemClick="doSearch()"> <mx:columns> <mx:DataGridColumn headerText="列车" dataField="TrainCode"/> <mx:DataGridColumn headerText="始发站" dataField="FirstStation"/> <mx:DataGridColumn headerText="终点站" dataField="LastStation"/> <mx:DataGridColumn headerText="开始" dataField="StartStation"/> <mx:DataGridColumn headerText="开始时间" dataField="StartTime"/> <mx:DataGridColumn headerText="到达" dataField="ArriveStation"/> <mx:DataGridColumn headerText="到达时间" dataField="ArriveTime"/> <mx:DataGridColumn headerText="公里数" dataField="KM"/> <mx:DataGridColumn headerText="耗费时间" dataField="UseDate"/> </mx:columns> </mx:DataGrid> </mx:Box>
SearchResultByTrainName.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Box xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%"> <mx:Script> <![CDATA[ import com.example.model.TrainModelLocator; [Bindable] private var model : TrainModelLocator = TrainModelLocator.getInstance(); ]]> </mx:Script> <mx:HBox width="100%" height="30"> <mx:Label text="{'搜索列车('+model.currentTrain.name+')的返回结果:'+model.currentTrain.journey.length}"/> <mx:Spacer width="100%"/> <mx:Button label="<--返回" click="model.currentState = ''"/> </mx:HBox> <mx:DataGrid width="100%" height="100%" dataProvider="{model.currentTrain.journey}"> <mx:columns> <mx:DataGridColumn headerText="序号" dataField="num" width="30"/> <mx:DataGridColumn headerText="车站" dataField="TrainStation" width="200"/> <mx:DataGridColumn headerText="到达时间" dataField="ArriveTime"/> <mx:DataGridColumn headerText="发车时间" dataField="StartTime"/> <mx:DataGridColumn headerText="里程" dataField="KM"/> </mx:columns> </mx:DataGrid> </mx:Box>
主界面中我们分别建立3个状态(包括默认的基础状态),用于显示3 个视图。
TrainSchedule.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:control="com.example.control.*" xmlns:business="com.example.business.*" xmlns:view="com.example.view.*" pageTitle="列车时刻表查询" currentState="{model.currentState}" verticalAlign="middle" viewSourceURL="srcview/index.html"> <mx:Script> <![CDATA[ import com.example.model.TrainModelLocator; [Bindable] private var model : TrainModelLocator = TrainModelLocator.getInstance(); ]]> </mx:Script> <mx:Style source="style.css" /> <business:Services id="services" /> <control:TrainController id="controller" /> <mx:states> <mx:State name="resultByTrainName"> <mx:RemoveChild target="{searchForm}"/> <mx:AddChild position="lastChild"> <view:SearchResultByTrainName /> </mx:AddChild> </mx:State> <mx:State name="resultByStationList"> <mx:RemoveChild target="{searchForm}"/> <mx:AddChild position="lastChild"> <view:SearchResultByStationList /> </mx:AddChild> </mx:State> </mx:states> <view:SearchForm id="searchForm"/> </mx:WindowedApplication>
建立服务调用类:
Services.mxml
<?xml version="1.0" encoding="utf-8"?> <business:ServiceLocator xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:business="com.adobe.cairngorm.business.*"> <mx:Script> <![CDATA[ import com.example.model.TrainModelLocator; ]]> </mx:Script> <mx:WebService id="trainService" wsdl="{TrainModelLocator.getInstance().wsWSDL}" showBusyCursor="true" useProxy="false"> <mx:operation name="getDetailInfoByTrainCode" resultFormat="xml"> <mx:request> <TrainCode>{TrainModelLocator.getInstance().currentTrain.name}</TrainCode> <UserID>{""}</UserID> </mx:request> </mx:operation> <mx:operation name="getStationAndTimeByStationName" resultFormat="xml"> <mx:request> <StartStation>{TrainModelLocator.getInstance().startStation}</StartStation> <ArriveStation>{TrainModelLocator.getInstance().arriveStation}</ArriveStation> <UserID>{""}</UserID> </mx:request> </mx:operation> </mx:WebService> </business:ServiceLocator>
代理
然后建立两个代理,分别用于调用WebService服务和本地数据库查询服务:
TrainDelegateWS.as
package com.example.business { import com.adobe.cairngorm.business.ServiceLocator; import mx.rpc.IResponder; public class TrainDelegateWS { public function TrainDelegateWS(responder : IResponder) { this.service = ServiceLocator.getInstance().getWebService("trainService"); this.responder = responder; } public function getTrainDetail() : void { call.addResponder( responder ); } public function getStationDetail() : void { call.addResponder( responder ); } private var responder : IResponder; } }
TrainDelegateDB.as
package com.example.business { import com.example.model.TrainModelLocator; import flash.data.SQLConnection; import flash.data.SQLResult; import flash.data.SQLStatement; import flash.events.SQLErrorEvent; import flash.events.SQLEvent; import flash.filesystem.File; import mx.collections.ArrayCollection; import mx.controls.Alert; import mx.rpc.IResponder; public class TrainDelegateDB { private var con:SQLConnection; private var conForStation:SQLConnection; private var file:File = File.applicationDirectory.resolvePath("data/TrainsInfo.db"); private var selectStmt:SQLStatement; public function TrainDelegateDB(responder : IResponder) { this.responder = responder; con = new SQLConnection(); conForStation = new SQLConnection(); con.addEventListener(SQLEvent.OPEN,openHandler); con.addEventListener(SQLErrorEvent.ERROR,errorHandler); conForStation.addEventListener(SQLEvent.OPEN,openHandlerByStation); conForStation.addEventListener(SQLErrorEvent.ERROR,errorHandler); } public function getTrainDetail() : void { con.openAsync(file); } public function getStationDetail() : void { conForStation.openAsync(file); } private var responder : IResponder; private function openHandler(e:SQLEvent):void { selectStmt = new SQLStatement(); selectStmt.sqlConnection = con; selectStmt.addEventListener(SQLEvent.RESULT, selectResult); var sql:String = "SELECT * FROM TrainStation WHERE TrainName = '"+TrainModelLocator.getInstance().currentTrain.name+"'"; selectStmt.text = sql; selectStmt.execute(); } private function openHandlerByStation(e:SQLEvent):void { selectStmt = new SQLStatement(); selectStmt.sqlConnection = conForStation; selectStmt.addEventListener(SQLEvent.RESULT, selectResultByStation); var sql:String = "SELECT * FROM TrainStation WHERE StationName = '"+TrainModelLocator.getInstance().startStation+"' or StationName = '"+TrainModelLocator.getInstance().arriveStation+"'"; selectStmt.text = sql; selectStmt.execute(); } private function errorHandler(e:SQLErrorEvent):void { Alert.show(e.error.message); Alert.show(e.error.details); } private function selectResult(event:SQLEvent):void { var result:SQLResult = selectStmt.getResult(); if(result.data != null) { var model : TrainModelLocator = TrainModelLocator.getInstance(); model.currentTrain.journey = new ArrayCollection(); nodeItem.num = count; count++; nodeItem.TrainStation = item.StationName; nodeItem.ArriveTime = item.ArriveTime; nodeItem.StartTime = item.LeaveTime; nodeItem.KM = item.Distance; model.currentTrain.journey.addItem(nodeItem); } model.currentState = "resultByTrainName"; } else { Alert.show("对不起,没有找到可用数据"); } con.close(); } private function selectResultByStation(event:SQLEvent):void { var result:SQLResult = selectStmt.getResult(); if(result.data != null) { var model : TrainModelLocator = TrainModelLocator.getInstance(); model.currentStaionList.trainStationList = new ArrayCollection(); if(item.TrainName == result.data[i].TrainName && item.StationName != result.data[i].StationName) { nodeItem.TrainCode = item.TrainName; //计算始发站 nodeItem.StartStation = model.startStation; nodeItem.StartTime = "点击查看详情"; nodeItem.ArriveStation = model.arriveStation; nodeItem.ArriveTime = "点击查看详情"; if(model.currentStaionList.trainStationList[j].TrainCode == item.TrainName) { hasNode = true; break f; } } if(!hasNode) model.currentStaionList.trainStationList.addItem(nodeItem); } } } model.currentState = "resultByStationList"; } else { Alert.show("对不起,没有找到可用数据"); } con.close(); } } }
(未完待续)