Проблема с Flex Google Maps API и глобальными вызовами функций - PullRequest
2 голосов
/ 02 февраля 2011

Я пытаюсь создать систему приложений на основе окон (если хотите, мини-GUI) в среде Adobe Air (Flex 4). При реализации перетаскивания окон я учитываю z-порядок, обновляя глубину теперь активированного окна из глобальной функции, которая обновляет скрытую переменную каждый раз, когда к ней обращаются (гарантируя, что выбранное окно всегда находится сверху). (Примечание: я выбрал глобальные функции вместо набора событий, потому что целью этого действия является немедленное получение возвращаемого значения, а не указание какой-либо другой части системы что-либо делать, поэтому я считаю, что это допустимое исключение из обычное предложение «использовать события для связи между объектами».) Я столкнулся с десятками возможных решений для создания и вызова этой глобальной функции, но единственное, что до сих пор работало, это:

event.target.parentApplication.obtainNewHigherDepth()

Как видите, на самом деле это не глобальный вызов функции, а вызов родительского элемента верхнего уровня (или более верхнего уровня), который содержит необходимую функцию. В моих тестовых случаях это работает просто отлично, даже когда я добавляю компоненты внутреннего содержимого в окна. Однако при добавлении карты Google в качестве содержимого окна нажатие на кнопки типа карты приводит к ошибке:

ReferenceError: Error #1069: Property parentApplication not found on com.google.maps.wrappers.
WrappableSprite and there is no default value.
at Window/selectWindow()[C:\Users\d04000196\Desktop\Projects\UI Concepting\ErrorExample\src\Window.mxml:18]

Похоже, что API Google Map пытается вызвать мой код в неверном контексте. Будучи новичком во Flex / Air, я не знаю, как связать соответствующий контекст, как это можно сделать с Javascript. Но это не должно быть необходимым.

Если есть лучший способ создать и вызвать действительно глобальную функцию (и использовать соответствующую глобальную переменную), эта проблема не выровненных контекстов не будет иметь значения. Или, если есть известное решение для этой конкретной проблемы с API Карт Google, это также могло бы работать как решение (но не как будущее).

Указанные ниже файлы представляют собой минимальный код, необходимый для иллюстрации проблемы.

Для настройки

  1. Загрузите указанные ниже файлы в стандартный пакет нового проекта Adobe Air через Flash Builder.
  2. Загрузите API Карт Google и добавьте библиотеку в проект .

Для иллюстрации ошибки

  1. Запустить приложение
  2. Нажмите кнопку «Открыть карту»
  3. Нажмите любую из кнопок типа карты в правом верхнем углу области карты

ExampleError.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication 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="800" height="600"
                       frameRate="60"
                       applicationComplete="init()">

    <fx:Script>
        <![CDATA[
            // ********************
            // THE PART IN QUESTION
            // ********************
            private var maxDepth:Number = 0;
            public function obtainNewHigherDepth():Number {
                return (maxDepth++);
            }

            private function openAMap(event:MouseEvent):void {
                var window:Window = new Window();
                var map:CustomMap = new CustomMap();

                window.x = 160;
                window.titleBarText.text = "Map"
                window.content.addElement(map);
                this.addElement(window);
            }

            private function init():void {
                openMapButton.addEventListener(MouseEvent.CLICK, openAMap);
                statusBar.visible = false;
            }
        ]]>
    </fx:Script>

    <s:VGroup x="10" y="10" width="135" height="580">
        <s:Button label="Open a Map" id="openMapButton" />
    </s:VGroup>
</s:WindowedApplication>

Window.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"
         xmlns:visuals="com.lsus.udop.visuals.*"
         width="400" height="400" depth="1"
         initialize="init()">

    <fx:Script>
        <![CDATA[
            import flash.events.MouseEvent;

            private var moving:Boolean = false;
            private var relativeX:Number;
            private var relativeY:Number;

            private function selectWindow(event:MouseEvent):void {
                // ********************
                // THE PART IN QUESTION
                // ********************
                this.depth = event.target.parentApplication.obtainNewHigherDepth();
            }

            private function windowDragMouseDown(event:MouseEvent):void {
                relativeX = event.stageX - this.x;
                relativeY = event.stageY - this.y;

                moving = true;

                this.systemManager.addEventListener(MouseEvent.MOUSE_MOVE, windowDragMouseMove, true);
                this.systemManager.addEventListener(MouseEvent.MOUSE_UP, windowDragMouseUp, true);
            }

            private function windowDragMouseMove(event:MouseEvent):void {
                event.stopImmediatePropagation();

                this.x = event.stageX - relativeX;
                this.y = event.stageY - relativeY;
            }

            private function windowDragMouseUp(event:MouseEvent):void {
                event.stopImmediatePropagation();

                moving = false;

                this.systemManager.removeEventListener(MouseEvent.MOUSE_MOVE, windowDragMouseMove, true);  
                this.systemManager.removeEventListener(MouseEvent.MOUSE_UP, windowDragMouseUp , true);
            }

            private function init():void {
                this.addEventListener(MouseEvent.MOUSE_DOWN, selectWindow);
                titleBar.addEventListener(MouseEvent.MOUSE_DOWN, windowDragMouseDown);
                this.depth = this.parentApplication.obtainNewHigherDepth();
            }
        ]]>
    </fx:Script>

    <s:Rect width="100%" height="100%">
        <s:fill>
            <s:SolidColor color="0x000000" />
        </s:fill>
    </s:Rect>

    <s:Group id="titleBar" top="0" left="0" right="0" height="20">
        <s:Label text="Title Bar Text" id="titleBarText" top="5" bottom="0" left="5" color="0xffffff" />
    </s:Group>

    <s:Group id="content" top="21" left="1" right="1" bottom="1" />

</s:Group>

CustomMap.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="100%" height="100%"
         initialize="init()">

    <fx:Script>
        <![CDATA[
            import com.google.maps.Map;
            import com.google.maps.MapEvent;
            import com.google.maps.MapType;
            import com.google.maps.controls.MapTypeControl;

            private function onMapReady(event:MapEvent):void {
                map.enableScrollWheelZoom();
                map.addControl(new MapTypeControl());
            }

            private function init():void {
                map.addEventListener(MapEvent.MAP_READY, onMapReady);
            }
        ]]>
    </fx:Script>

    <maps:Map xmlns:maps="com.google.maps.*"
              url="http://code.google.com/apis/maps/"
              key="ABQIAAAAiVMBdjzjhpqA-qSxuuT0cRT2yXp_ZAY8_ufC3CFXhHIE1NvwkxQ4igt7gOyr4x11lp3ETKR2fOH5Hw"
              sensor="false"
              width="100%" height="100%" id="map" />
</s:Group>

Обновление

Обнаружил другой вопрос только сейчас (никогда не выходит из строя, не так ли?), Это:

FlexGlobals.topLevelApplication

, кажется, дает мне то, что я ищу. Недостатком является отсутствие безопасности, если мой оконный компонент когда-либо используется за пределами этого конкретного приложения, но поскольку это не планируется, этого должно быть достаточно. Тем не менее, если есть лучшее решение, я бы хотел услышать его.

Ответы [ 2 ]

0 голосов
/ 03 февраля 2011

Я думаю, вам следует сделать следующее:

  1. Создать пользовательское событие с именем DepthRequestEvent
  2. Добавить прослушиватель в основное приложение (ExampleError.mxml): addEventListener(DepthRequestEvent.REQUEST_DEPTH, obtainNewHigherDepth).
  3. Добавление прослушивателя в Window.mxml: addEventListener(DepthRequestEvent.REQUEST_RESULT, handleDepthRequestResult).
  4. Отправка DepthRequestEvent.REQUEST_DEPTH из Window.mxml
  5. В функции getNewHigherDepth () основного приложения отправьте событие DepthRequestEvent.REQUEST_RESULT последобавив значение depth к событию.
  6. Функция handleDepthRequestResult() в Window.mxml фиксирует это, и вы можете получить переменную event.depthValue из параметра события

Обновление: ВWindow.mxml добавьте прослушиватель событий, используя: FlexGlobals.topLevelApplication.addEventListener(.....

Бинго, слабо связанные классы!(звонить родителям из класса - это вроде нет-нет)

0 голосов
/ 03 февраля 2011

Эй, я только что действительно быстро прочитал, хотя, может быть, я ошибаюсь, но я думаю, что вы должны взглянуть на PopUpManager . Заботится о глубине сортировки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...