0

I have a test case demonstrating my problem.

It runs instantly, when you add the following 4 short files into a new Flex Mobile project in Flash Builder 4.6:

Screenshot

src/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>

src/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>

src/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);
            }
        }
    }
}

My question is: provided I have many appropriately named FXG files in the assets sub-directory (in my real application I have spades_queen.fxg, spades_king.fxg, spades_ace.fxg etc.) - how can I select an FXG file at the runtime?

The commented line above gives me the runtime error:

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

When I move the src/assets/en/Star.fxg to src/Star.fxg everything works...

ketan
  • 19,129
  • 42
  • 60
  • 98
Alexander Farber
  • 21,519
  • 75
  • 241
  • 416

2 Answers2

1

I'm guessing you're getting this runtime error because the Star.fxg is not compiled into the finished app because it is not used by name. It is confusing why moving the location of the file would bypass the error.

But, try adding the file reference in their. Import it:

import assets.en.Star

And create a dum instance that you never use just so the file is sure to be compiled into the app:

private var myStart :Star;

Then this line, should work:

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

You can also use a compiler argument to force the FXG class to be compiled into your finished application.

I use this same exact approach in my Casual Game, built in Flex.

However, the weird thing is why moving the file to a different directory causes things to work w/o issues. That is a puzzler, unless you were referencing the wrong package. (AKA assets.en.Star--as you use in code--verse src/assets/Star which you reference in the question).

JeffryHouser
  • 39,401
  • 4
  • 38
  • 59
0

You don't need to do anything with getDefinitionByName, you can simply create a new instance of Start and use addElement to place it on the stage.

        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);
        }

In order for this to work you have to import the package that your FXP is in. Possibly assets.Star

You can switch types by creating a new instance as well.

Say you have Star.fxg and King.fxg in assets

import assets.Star;
import assets.King;

var star:Star = new Star();
var king:King = new King();
francis
  • 5,889
  • 3
  • 27
  • 51
  • Yes, this works - at compile time. But my question is: how to select, load and display an FXG at the runtime. For example when you have a **var WHAT:String** - which can hold either *Star* or *King*. – Alexander Farber Apr 16 '12 at 13:47
  • 1
    You can just pass in a string and use it in a switch statement. switch(item){ case "star": return new Star(); break; case "king" return new King(); break } – francis Apr 16 '12 at 13:50
  • You could use getDefinitionByName on a class name. You just have to make sure it's imported – francis Apr 16 '12 at 14:05
  • If you look at my question it is imported, but I can't get getDefinitionByName to work - unless I copy all FXG into the root src/ dir - and I'd like to avoid that and keep the 52 FXG files for playing cards in src/assets dir. – Alexander Farber Apr 16 '12 at 14:22
  • @f-a Importing it is only half the battle; the Flex compiler will remove that class if it isn't used explicitly. You also need a variable of that type. You do not have to instantiate it. Or you could force the compilre not to remove the class w/ a Compiler argument. I also think the "switch statement approach" sucks. Functional, but not flexible. – JeffryHouser Apr 17 '12 at 03:47