Выберите файл FXG во время выполнения - по его имени

У меня есть тестовый пример, демонстрирующий мою проблему.

Он запускается мгновенно, когда вы добавляете следующие 4 коротких файла в новый проект Flex Mobile в Flash Builder 4.6:

Скриншот

источник/TestFXG.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:ViewNavigatorApplication 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    firstView="Home">
</s:ViewNavigatorApplication>

src/assets/en/Star.fxg:

<?xml version='1.0' encoding='UTF-8'?>
<fxg:Graphic xmlns:fxg="http://ns.adobe.com/fxg/2008" version="2">    
    <fxg:Path x="9.399" y="10.049" data="M 82.016 78.257 L 51.895 69.533 L 27.617 89.351 L 26.621 58.058 L 0.231 41.132 L 29.749 30.52 L 37.714 0.241 L 56.944 24.978 L 88.261 23.181 L 70.631 49.083 Z">
        <fxg:fill>
            <fxg:SolidColor color="#FFFFFF"/>
        </fxg:fill>
        <fxg:stroke>
            <fxg:SolidColorStroke 
                caps="none" 
                color="#FFFF66" 
                joints="miter" 
                miterLimit="4" 
                weight="10"/>
        </fxg:stroke>
    </fxg:Path>
</fxg:Graphic>

источник/Home.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark"
        xmlns:my_components="*"
        title="Display random amount of stars">

    <fx:Script>
        <![CDATA[
            import Star;
            import spark.core.SpriteVisualElement;

            private static const STAR:SpriteVisualElement = new Star();
        ]]>
    </fx:Script>    

    <my_components:MyComp />
</s:View>

источник/MyComp.as:

package {
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.utils.getDefinitionByName;
    import mx.core.UIComponent;
    import spark.core.SpriteVisualElement;
    import assets.Star;

    public class MyComp extends UIComponent {
        private static const WHAT:String = "assets.en.Star";

        override protected function createChildren():void {
            super.createChildren();

            for (var i:uint = 0; i < 3; i++) {
                var star:Star = new Star();
                //var star:SpriteVisualElement = new (getDefinitionByName(WHAT) as Class)();
                star.x = Math.random() * 100;
                star.y = Math.random() * 100;
                addChild(star);
            }
        }
    }
}

Мой вопрос: если у меня есть много файлов FXG с соответствующими именами в подкаталоге assets (в моем реальном приложении у меня есть spades_queen.fxg, spades_king.fxg, spades_ace.fxg и т. д.) - как я могу выбрать файл FXG во время выполнения?

Закомментированная строка выше дает мне ошибку времени выполнения:

ReferenceError: Error #1065: Variable Star is not defined.
    at global/flash.utils::getDefinitionByName()

Когда я перемещаю src/assets/en/Star.fxg в src/Star.fxg, все работает...


person Alexander Farber    schedule 16.04.2012    source источник


Ответы (2)


Я предполагаю, что вы получаете эту ошибку времени выполнения, потому что Star.fxg не скомпилирован в готовое приложение, потому что он не используется по имени. Это сбивает с толку, почему перемещение местоположения файла может обойти ошибку.

Но попробуйте добавить ссылку на файл в их. Импортируйте это:

import assets.en.Star

И создайте фиктивный экземпляр, который вы никогда не используете, чтобы файл обязательно скомпилировался в приложение:

private var myStart :Star;

Тогда эта строка должна работать:

var star:SpriteVisualElement = new (getDefinitionByName(WHAT) as Class)();

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

Я использую точно такой же подход в своей казуальной игре, встроенный во Flex.

Однако странно то, что перемещение файла в другой каталог приводит к тому, что все работает без проблем. Это загадка, если вы не ссылались на неправильный пакет. (AKA assets.en.Star — как вы используете в коде — стих src/assets/Star, на который вы ссылаетесь в вопросе).

person JeffryHouser    schedule 17.04.2012

Вам не нужно ничего делать с getDefinitionByName, вы можете просто создать новый экземпляр Start и использовать addElement, чтобы разместить его на сцене.

        for (var i:uint = 0; i < 3; i++) {
            var star:Star = new Star();
            star.x = Math.random() * 100;
            star.y = Math.random() * 100;
            addElement(star);
        }

Чтобы это работало, вам нужно импортировать пакет, в котором находится ваш FXP. Возможно, assets.Star

Вы также можете переключать типы, создавая новый экземпляр.

Допустим, у вас есть Star.fxg и King.fxg в активах.

import assets.Star;
import assets.King;

var star:Star = new Star();
var king:King = new King();
person francis    schedule 16.04.2012
comment
Да, это работает - во время компиляции. Но мой вопрос: как выбрать, загрузить и отобразить FXG во время выполнения. Например, если у вас есть var WHAT:String, который может содержать либо Star, либо King. - person Alexander Farber; 16.04.2012
comment
Вы можете просто передать строку и использовать ее в операторе switch. switch(item){ case star: return new Star(); ломать; case king вернуть новый King(); ломать } - person francis; 16.04.2012
comment
Вы можете использовать getDefinitionByName для имени класса. Вам просто нужно убедиться, что он импортирован - person francis; 16.04.2012
comment
Если вы посмотрите на мой вопрос, он импортирован, но я не могу заставить работать getDefinitionByName - если я не скопирую все FXG в корневой каталог src/ - и я хотел бы избежать этого и сохранить 52 файла FXG для игральных карт в источник/активы директор. - person Alexander Farber; 16.04.2012
comment
@f-a Импортировать это только полдела; компилятор Flex удалит этот класс, если он не используется явно. Вам также нужна переменная этого типа. Вам не нужно создавать его экземпляр. Или вы можете заставить компилятор не удалять класс с аргументом компилятора. Я также думаю, что подход оператора switch отстой. Функционально, но не гибко. - person JeffryHouser; 17.04.2012