Взаимодействие с приложением Flex из Flash CS3 - PullRequest
2 голосов
/ 15 марта 2011

У меня есть программа для просмотра панорам во Flash, в которую я хочу встроить небольшое приложение Flex.Мне удалось загрузить Flex SWF во Flash следующим образом:

private var loader:Loader = new Loader();

var req:URLRequest = new URLRequest("SimpleImageViewer.swf");
loader.load(req);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imgViewerLoaded);

imgViewerLoaded(event:Event)
{
    imageViewer = loader.content;
    addChild(imageViewer);
    imageViewer.showImage("test.jpg", "Test Image");
}

Теперь мне нужно иметь возможность вызывать метод в imageViewer, который я определил в своемПриложение Flex выглядит следующим образом:

public function showImage(source:String, heading:String = ""):void
{
    //Show the image
}

Оно также добавляется в ExternalInterface с помощью

ExternalInterface.addCallback("showImage", showImage);

Как я могу вызвать этот метод из моей AS3 Flash?Просто вызывая его как imageViewer.showImage(...), выдает эту ошибку:

ReferenceError: Ошибка # 1069: свойство showImage не найдено в _SimpleImageViewer_mx_managers_SystemManager и значение по умолчанию отсутствует.

в UserInterface / imgViewerLoaded ()

Это весь файл SimpleImageViewer.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="100" minHeight="100" backgroundColor="#2B2B2B" creationComplete="onCreationComplete(event)" backgroundGradientAlphas="[1.0, 1.0]" backgroundGradientColors="[#2B2B2B, #2B2B2B]" verticalScrollPolicy="off" horizontalScrollPolicy="off">
<mx:Image x="0" y="0" width="100%" height="100%" horizontalAlign="center" verticalAlign="middle" scaleContent="true" maintainAspectRatio="true" id="picture"/>
<mx:Image width="100%" height="42" x="0" y="0" id="headingBg" source="@Embed(source='/bilder/topList.png')" scaleContent="true" maintainAspectRatio="false"/>
<mx:Label x="4" y="0" width="100%" height="43" id="headingTxt" fontFamily="Arial" fontSize="32" color="#FFFFFF" textAlign="center"/>

<mx:Script>
    <![CDATA[
        import mx.events.FlexEvent;
        import mx.events.ResizeEvent;

        public function showImage(source:String, heading:String = ""):void
        {
            picture.source = source;
            picture.load();
            headingTxt.text = heading;
        }

        protected function onCreationComplete(event:FlexEvent):void
        {               
            ExternalInterface.addCallback("showImage", showImage);
            Security.allowDomain("localhost");
        }


    ]]>
</mx:Script>
</mx:Application>

и интерфейс ImageViewer:

package tikab.lizzan
{
    public interface ImageViewer
    {
        function showImage(source:String, heading:String = ""):void ;   
    }
}

Ответы [ 3 ]

2 голосов
/ 16 марта 2011

Отредактировано:

Из документации flex:

Если приложение загружено в другое приложение, SystemManager все равно будет создан, но не будет управлять окном приложения, в зависимости отпо безопасности и правилам домена.Вместо этого это будет содержимое загрузчика, которое загрузило его и просто будет являться родительским объектом для подпрограммы

Другими словами: при загрузке приложения Flex в другое приложение свойство contentобъекта загрузчика будет указывать не непосредственно на само приложение, а на экземпляр SystemManager , который действует как родительский объект фактического объекта приложения.Поэтому ваши вызовы методов должны быть направлены на loader.content.getChildAt(0).

Чтобы сделать это безопасным для типа способом:

  1. создать интерфейс
  2. иметь ваш гибкий документкласс реализует это
  3. приведение первого потомка содержимого вашего объекта Loader к тому же интерфейсу

Или (не типобезопасно, но быстро) просто вызовите метод, используя синтаксис скобок:

loader.content.getChildAt(0)["showImage"]();

или приведите loader.content.getChildAt(0) к динамическому типу, такому как Object или MovieClip, как рекомендовано @_asMan.

Edit:

Вы также пропустили некоторые важные операторы объявленияв вашем коде.Вот как должна выглядеть функция imageViewerLoaded:

function imgViewerLoaded(event:Event)
{
    var imgViewer:MovieClip = loader.content.getChildAt(0) as MovieClip;
    addChild(loader.content);
    imgViewer.showImage("test.jpg", "Test Image");
}

function и var должны никогда считаться необязательными - они помогают вам избежать путаницы в иерархии классов и типахРекомендации.(Вы можете опустить var, если вы, конечно, imgViewer объявили как переменную-член где-то еще). Я также изменил имя с "imageViewer", чтобы не было двусмысленной ссылки - сообщение об ошибке, которое вы разместили ниже, подразумевает риск;)

0 голосов
/ 16 марта 2011

Не уверен, что это сработает, но пытались ли вы рассматривать его как объект?

imgViewerLoaded(event:Event)
{
    imageViewer = loader.content;
    addChild(imageViewer);
    Object( loader.content ).showImage();
}

или, возможно, использовать в качестве базового класса, если он у вас назначен.Я использовал приложение в качестве примера

var loadedApp:Application = Application( loader.content );
loadedApp.showImage();
0 голосов
/ 15 марта 2011

РЕДАКТИРОВАТЬ # 2:

Попробуйте это:

function imgViewerLoaded(event:Event):void
{
    var manager:SystemManager = event.target.content as SystemManager;
    var content:ImageViewer = manager.application as ImageViewer;
    addChild(viewer);
    viewer.showImage();
}

Это основано на полезной информации Weltraumpirat о том, что тип контента на самом деле является объектом SystemManager. Исходя из всего, что я вижу, я думаю, что это сработает и будет немного чище. Удачи!

** конечно, обратите внимание, что вам придется изменить опубликованный MXML для реализации вашего интерфейса, так как я подозреваю, что вы уже сделали

РЕДАКТИРОВАТЬ # 1:


Исходя из ваших сообщений выше, я обнаружил, что мой код выполняет то же самое:

private function loadCompleted(event:Event):void {
        currentClip = event.target.content as MovieClip;
        loader.unload();
        displayClip();
}

Так что вы можете попробовать просмотреть содержимое:

event.target.content

Попробуйте следующий код, чтобы увидеть, что это за тип, затем используйте эту информацию для приведения:

var contents:* = event.target.content;
var className:String = flash.utils.getQualifiedClassName( contents );
trace("Class name was: " + className);

Оттуда вы можете получить более легкий доступ к методу с помощью следующего кода:

function imgViewerLoaded(event:Event):void
{
    var viewer:TypeThatYouFound = loader.content as TypeThatYouFound;
    addChild(viewer);
    viewer.showImage();
}

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

Надеюсь, это поможет,

~ gMale


Ok. Поэтому я даже не буду спрашивать, почему вы делаете это в обратном порядке (обычно вы переходите от флеш-памяти к гибкой, а не наоборот. Обычно SWF-файлы импортируются, а не Flex-SWF-файлы).

Первое, что приходит на ум, это то, что вы, вероятно, не создаете класс для своего кода Flex. Чтобы раскрыть ваши функции, вам нужно сообщить кому-то, что ваш объект отличается от обычного SimpleImageViewer.

В зависимости от того, как вы проектировали вещи, вам может потребоваться создать собственный класс, такой как

public class MySimpleImageViewer extends SimpleImageViewer {
        public function showImage(source:String, heading:String = ""):void {
            //Show the image
        }
}

Затем пусть ваш файл MXML создает это с использованием следующего синтаксиса:

<local:MySimpleImageViewer />

Поскольку ваш подход немного неортодоксален, трудно сказать, что именно вам нужно. Если это не поможет, попробуйте опубликовать свой код Flex, и мы сможем перейти оттуда ...

Надеюсь, это поможет,

~ gMale

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