您的位置:首页 > 其它

Arcgis api for flex项目实例—开发篇(5):查询

2014-10-10 11:09 316 查看
前文已完成了基本的地图工具,现在要开始一个GIS项目的核心内容——查询。按这个项目的设计,查询要分为政区查询和关键字查询两类,其实都大同小异,这里就只按关键字查询来写了。

查询在一个系统中一般有几个要素,一是要有条件输入,这里就是一个文本框和一个搜索按钮;二是要有结果列表,项目设计的左侧区域就承担了这个任务,计划用一个list来实现;三是要有地图展示,地图展示主要是把查询结果在地图上用符号标注出来,并且能提供一个infowindow来展示详细信息。本节内容不包括第三点,与地图的一些联动在下节单独介绍。

首先我要调整一下框架的布局,主要是左侧栏,先看mxml。

AHTour.mxml:

<!—将左侧扩充为300的宽度-->
<s:BorderContainer left="0" top="80" bottom="0" width="300" backgroundColor="#FFFFFF"
borderWeight="2">
<mx:TabNavigator id="b_left" left="5" right="5" top="5" bottom="5">
<s:NavigatorContent width="100%" height="100%" label="景点查询">
<!--提供一个group用于界面的切换-->
<s:Group id="mainContent" left="10" right="10" top="5" bottom="10">
<component:LeftSearchPage left="0" right="0" top="0" bottom="0" QueryStart="QueryStartHandler(event)">
</component:LeftSearchPage>

</s:Group>
</s:NavigatorContent>
</mx:TabNavigator>
</s:BorderContainer>
<s:BorderContainer id="b_map" left="300" right="0" top="80" bottom="0">
</s:BorderContainer>


代码中我略去了政区查询的布局,核心就是左侧栏扩充为300的宽度,这是为了显示的需要,map的border相应的left也置为300。而后就是我把Tab中的内容用一个group框了起来,并把之前的textInput和搜索按钮放到一个组件LeftSearchPage中去,这是为了方便控制界面得切换,LeftSearchPage代码在后面给出。

先来看查询,因为是要查询数据库,要用到后台代码。我在spring mvc当中做了一个查询,spring mvc不是本文重点,我只贴部分核心代码:

//dao层中的查询
public List<?> getDataByCol(String tabName, String colName,String colValue) {
String sqlStr = "select * from "+tabName+" where "+ colName + " like '%"+ colValue+"%'";
return jdbcTemplate.queryForList(sqlStr);
}
//service层中调用dao
public List<?> getDataByCol(String tabName,String colName,String colValue)
{
return     baseDao.getDataByCol(tabName, colName, colValue);
}
//数据获取controller
@SuppressWarnings({ "rawtypes", "unchecked" })
@RequestMapping("/query")
public @ResponseBody HashMap Query(HttpServletRequest request, @RequestParam("keyword")String keyword) throws Exception
{
HashMap map = new HashMap();
byte bb[];
bb = keyword.getBytes("ISO-8859-1"); //以"ISO-8859-1"方式解析字符串
keyword= new String(bb, "UTF-8"); //再用"utf-8"格式表示字符串
map.put("result", baseService.getDataByCol("sp_tour", "name", keyword));
map.put("success", true);
return map;
}


写完服务后,形成一个http接口提供数据:http://localhost:8080/ahlv/base/query.html?keyword=XXXX,用合肥野生动物园做关键字可以获得这样的结果:

{
"result":[
{
"NAME":"合肥野生动物园",
"URL":"http://tour.ahta.com.cn/Scenic---view2011---1475.shtml",
"REGION":"合肥市",
"LON":117.16,
"LAT":31.83
}
],
"success":true
}


下面回到前台,我们先设计一个用于查询的类,先上代码:

QueryTool.as

//要注册两个事件,在完成时传递结果,失败时传递错误信息
[Event(name="QueryCompleted", type="tool.CustomEvent")]
[Event(name="QueryFailed", type="tool.CustomEvent")]
public class QueryTool extends EventDispatcher
{
public function QueryTool()
{
}
public function Query(keyword:String):void
{
var httpRequest:HTTPService = new HTTPService();
httpRequest.url = "http://localhost:8080/ahlv/base/query.html";
httpRequest.method = "GET";
httpRequest.addEventListener(ResultEvent.RESULT,resultHandler);
httpRequest.addEventListener(FaultEvent.FAULT,faultHandler);
httpRequest.send({keyword:keyword});
function resultHandler(event:ResultEvent):void
{
var resultObj:Object = JSON.parse(event.result.toString());
//判断是否失败
if(!Boolean(resultObj.success))
{
dispatchEvent(new CustomEvent(CustomEvent.QueryFailed,"查询失败!"));
return;
}
//将结果转换为graphic
var resultArray:ArrayCollection = new ArrayCollection();
for each(var gobj:Object in resultObj.result)
{
var picSymbol:PictureMarkerSymbol = new PictureMarkerSymbol("image/locator.png",22,28,0,14,0);
var graphic:Graphic = new Graphic(new MapPoint(Number(gobj.LON),Number(gobj.LAT)),picSymbol,gobj);
resultArray.addItem(graphic);
}

dispatchEvent(new CustomEvent(CustomEvent.QueryCompleted,resultArray));
}
}

protected function faultHandler(event:FaultEvent):void
{
dispatchEvent(new CustomEvent(CustomEvent.QueryFailed,event.fault.faultString));
}
}


这里用到了CustomEvent这个事件类,这也是会被项目中反复用到的一个类,来看一下它的定义。这个自定义事件类是标准写法,上面定义了四种事件类型,现在要用的是QueryCompleted和QueryFailed,其他的后面很快会用到。

CustomEvent.as

public class CustomEvent extends Event
{
public static const QueryCompleted:String = "QueryCompleted";
public static const QueryStart:String = "QueryStart";
public static const BacktoFront:String = "BacktoFront";
public static const QueryFailed:String = "QueryFailed";
public var data:Object;
public function CustomEvent(type:String,data:Object = null)
{
super(type,bubbles,cancelable);
this.data = data;
}

override public function clone():Event{

return new CustomEvent(type,data);

}
}


当然光能拿到数据还不够,还需要配置好数据显示的列表,这就需要一个LeftResultPage,这个Page就是在查询成功后替换LeftSearchPage,用于显示结果列表。

LeftSearchPage.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:VGroup 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="270" gap="0">
<!--注册事件用于点击返回按钮回到首页-->
<fx:Metadata>
[Event(name="BacktoFront", type="tool.CustomEvent")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import tool.CustomEvent;

[Bindable]
private var result:ArrayCollection;
protected function back_clickHandler(event:MouseEvent):void
{
dispatchEvent(new CustomEvent(CustomEvent.BacktoFront));
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<s:Group width="100%" height="30">
<s:Label left="0" text="{'共查到'+ result.length+'个结果'}" verticalCenter="0"/>
<mx:LinkButton right="0" label="返回" click="back_clickHandler(event)"
verticalCenter="0"/>
</s:Group>
<s:List id="list_Result" width="100%" height="100%" itemRenderer="renderer.listRenderer" dataProvider="{result}"></s:List>
</s:VGroup>


这里用到了一个listRenderer,这是要实现一个比较复杂的list项必须的,好吧,不要怕烦,写一下这个renderer。注意这里的data是一个graphic,要照着graphic取属性的格式来写。

listRenderer.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true" width="250" height="70">

<s:Image left="10" source="image/locator.png" verticalCenter="0"/>
<s:VGroup left="42" right="10" top="10" bottom="10">
<s:Label color="#19AF01" fontSize="14" text="{data.attributes.NAME}"/>
<s:Label color="#8D8D8D" text="{data.attributes.REGION}"/>
</s:VGroup>
</s:ItemRenderer>


再来看看如何使用这个查询类来进行查询,首先看一看LeftSearchPage是怎么写的。

LeftSearchPage.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Group 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:Metadata>
[Event(name="QueryStart", type="tool.CustomEvent")]
</fx:Metadata>

<fx:Script>
<![CDATA[
import mx.controls.Alert;

import tool.CustomEvent;
protected function query_clickHandler(event:MouseEvent):void
{
if(txt_Keyword.text.length > 0)
dispatchEvent(new CustomEvent(CustomEvent.QueryStart,txt_Keyword.text));
else
Alert.show("请输入关键字!");
}
]]>
</fx:Script>

<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<s:TextInput id="txt_Keyword" left="5" right="65" top="0" height="22" prompt="请输入关键字"/>
<s:Button right="10" top="0" width="50" height="22" label="查询"
click="query_clickHandler(event)"/>
</s:Group>


这边定义了QueryStart事件,在搜索按钮点击时把关键字传递给AHTour.mxml,这是为了方便页面切换和处理过期数据,把查询类放到主页面中去执行,子页面只控制自己的界面元素。下面看AHTour里需要加的QueryStartHandler和backtofrontHandler两个事件监听:

AHTour.mxml

//主页Query
private function QueryStartHandler(event:CustomEvent):void
{
// TODO Auto-generated method stub
var query:QueryTool = new QueryTool();
query.Query(event.data.toString());
query.addEventListener(CustomEvent.QueryCompleted,queryCompletedHandler);
query.addEventListener(CustomEvent.QueryFailed,queryFailedHandler);
function queryCompletedHandler(event:CustomEvent):void
{
var queryResult:LeftResultPage = new LeftResultPage();
queryResult.map = map;
queryResult.result = event.data as ArrayCollection;
//返回主页的事件监听
queryResult.addEventListener(CustomEvent.BacktoFront,backtofrontHandler);
queryResult.bottom = 0;
queryResult.top = 0;
mainContent.removeAllElements();
mainContent.addElement(queryResult);
}
function queryFailedHandler(event:CustomEvent):void
{
Alert.show(event.data.toString());
}
}

private function backtofrontHandler(event:Event):void
{
var searchPage:LeftSearchPage = new LeftSearchPage();
searchPage.left = 0;
searchPage.right = 0;
searchPage.top = 0;
searchPage.bottom = 0;
//启动查询的事件监听
searchPage.addEventListener(CustomEvent.QueryStart,QueryStartHandler);
mainContent.removeAllElements();
mainContent.addElement(searchPage);
}


这样就可以了,查询结果可以显示于这个列表中,点击列表的返回按钮又可以返回到查询页,触发下一次查询。看一下结果:



这一节内容有点长,主要是因为布局和事件带来了附加的代码。现在还只是把结果显示了出来,下一节将介绍把这个结果与地图联动的一系列做法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: