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

前文已完成了基本的地图工具,现在要开始一个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);
            }

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

这一节内容有点长,主要是因为布局和事件带来了附加的代码。现在还只是把结果显示了出来,下一节将介绍把这个结果与地图联动的一系列做法。

时间: 2024-09-27 11:04:24

Arcgis apis for flex项目实例—开发篇(5):查询的相关文章

Arcgis apis for flex项目实例—开发篇(1):地图浏览

前文已经明确数据用天地图,这样的选择一来是免费,二来各种来源的数据都大同小异,天地图用的2000坐标系是常见的经纬度,方便专题数据叠加. 闲话少说,看一下arcgis api for flex是如何吃定天地图的吧.首先要明确的是我们需要用到四个天地图瓦片服务,分别是经纬度地图底图.经纬度地图中文注记.经纬度影像底图.经纬度影像中文注记,详情可以参阅http://www.tianditu.com/guide/index.html.各种服务形式上都差不多,我们来写一个天地图图层类. 首先新建一个类,

Arcgis apis for flex项目实例—开发篇(6):自己的infowindow

前文已经完成了从数据库查询旅游景点的工作,下面就是要把这些查询的结果显示到地图上,同时要实现查询列表和地图的联动.也就是点击列表中的某一项,地图能定位至该位置并弹出infowindow. 这个开发工作本身没有太大的难度,但是我认为的增加了一点障碍,因为我不太喜欢arcgis api自带的infowindow,我需要自己做一个,这一节内容就从这个DIY的infowindow开始.首先来设计一下这个窗体,为了表示不抄袭,这个infowindow改名PopupWindow. PopupWindow.m

Arcgis apis for flex项目实例—开发篇(2):鹰眼图

在底图调用完成后,我们要为地图添加一些工具,首先就是出场率很高的鹰眼图.我这里的鹰眼图是从ESRI的Flex Viewer中剥离出来的,申明一下,怕ESRI说我侵权.经常有人质疑我为什么不直接用Viewer而要费心思自己去写一些组件.我个人的经验是Viewer东西太多了,很臃肿,对于我们这样有整洁强迫症的人来说工程里存在大量用不着的代码非常难受,其实也不光是心理作用了,确实Viewer不经过大量优化会加载比较慢.但是,Viewer中有很多思想和很多组件是非常好用的,比如这个鹰眼,所以我们依然要借

Arcgis apis for flex项目实例—开发篇(3):地图级别控制器

地图级别控制器俗称“鱼骨头”,这几乎是Web地图的标配了.ESRI的flex api自带了级别控制器叫做zoomSlider,我觉得是非常的难看,难看的和“鱼骨头”都不太沾边,给任何客户提供这样的一个组件都是非常不严肃的事情,我的选择是要么索性不提供这个工具,要么,就自己做一个.这是我做的组件的效果: 这个组件可以整合很多的地图工具,本节只讨论中间的那个滑块部分,就是从“+”到“-”之间的部分,其他的工具留给下一节. 先来看布局,一个Group把所有的部件框起来,放下两个按钮.两个Rect.两个

Arcgis apis for flex项目实例—开发篇(4):测距工具

这一节就是要完成一个很常见的动态测距工具,一边绘制测距线,一边给出每个节点的结果.顺便把基本的四个方向的移动.放大.缩小.自由平移等map工具都补全. 四个方向的箭头很简单,我直接贴代码了. <commonitem:NavButton id="btn_up" top="10" horizontalCenter="0" icon="image/up_arrow.png" click="map.panUp()&qu

Arcgis apis for flex项目实例—美工篇(1):样式与布局

前文已完成基本的功能,该是进入美工阶段了.我也只是一个小前端程序员,没有能力把页面做的美如画,美工的原则只有两点:一是采用大众化的页面风格,配色和谐,符合大多数用户的操作习惯:二是尽可能采用自定义控件样式,不要出现flex自带的控件样式.这一节先简要介绍一下总体的样式和布局.改变一下习惯,先美工处理过后的效果图: 从最终的结果看主要由几点改变:首先是有了主题色——绿.蓝.橙为主的组合:其次是加入了一些页面元素,页面整体变得丰满:然后是很多控件样式发生了变化,如滚动条.地图切换按钮.搜索框.工具按

Arcgis apis for flex项目实例—谋局篇(2):界面设计

界面设计是谋局当中第二个任务,也是很重要的,这个和概念设计排名不分先后.合理的界面布局会给用户带来非常舒心的体验,在项目之处就能把界面风格和布局确定下来,更是可以让后面的开发事半功倍. First:基本布局.我们不是艺术家,不是激进派,四平八稳符合我们的风格,也符合快速开发的要求,布局就采用上天下地,左表右图的经典百度地图式布局,下面开始. 基本元素:三个border.一个是主窗口,也就是map,一个border是网站的头部,也就是展示个名字放点图片当好看的:一个border是左侧栏,用于查询输

南沙政府应急系统之GIS一张图(arcgis api for flex)讲解(一)GIS一张图的系统开发环境以及flexviewer框架

系统的GIS功能实现是基于arcgis api for flex,首先附上系统的主界面图,接下来的是对主界面的模块功能详细讲解: 一.GIS环境软件安装 (1)arcgis desktop的安装,要是不想对地图数据进行样式配置或者数据加工的话,这步可以跳过不用安装,详细的安装步骤见这里: (2)arcgis server的安装,这个是必须的,用来发布webgis的地图服务,比如地图基础服务,路径分析的网络服务,地理编码服务等等,详细的安装步骤见这里: (3)arcsde直连创建地理企业数据库,为

《ArcGIS Runtime SDK for Android开发笔记》——(9)、空间数据的容器-地图MapView

1.前言 在上一篇内容里介绍了 关于ArcGIS Android开发的未来(“Quartz”版Beta)相关内容,期间也提到了关于API接口的重构,开发思路的调整,根据2015UC资料也可以知道新版预计将在明年的时候推出.届时在开发思路上将会往新版迁移. 总的来说,虽然“Quartz”版的开发思路有所变化,但总体变化不大,这里我将继续以现有正式发布版本为主梳理ArcGIS Runtime SDK for Android 开发内容. 参考API版本号:version 10.2.7.后续内容若不做特