开发者

Accessing <mx:Image> from AS class

I want to draw something on an <mx:Image> I have in my .mxml file, but I want to keep my drawing implementation in开发者_Python百科 a separate AS class.

How can I access my drawing AS class in my .mxml?


I think what your are asking is how to keep your actionscript files separate from the MXML files that contain your designs. The answer is simple:

Create your actionscript file. Include only methods in this file, and do not wrap the code in a package or class definition. The file should look like the following:

import mx.controls.Alert;

// ActionScript file
/**
 *
 * Created By jviers
 * Created on Apr 14, 2011
 * 
 *
 */

public function hello():Alert{
    Alert.show("Hello World!");
}

Create your MXML file that contains your "Design" components. Create a Script element on this mxml file and set the source to the relative path of your ActionScript file. The MXML should look like this:

<?xml version = "1.0" encoding = "utf-8"?>
<s:Application xmlns:fx = "http://ns.adobe.com/mxml/2009"
               xmlns:s = "library://ns.adobe.com/flex/spark"
               xmlns:mx = "library://ns.adobe.com/flex/mx"
               minWidth = "955"
               minHeight = "600">

    <fx:Script>
        <![CDATA[
            protected function button1_clickHandler ( event : MouseEvent ) : void {
                // TODO Auto-generated method stub
                hello ();
            }
        ]]>
    </fx:Script>

    <fx:Declarations>

        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>

    <fx:Script source = "./scratch/MyFile.as" />

    <s:Button label = "Show Alert" click = "button1_clickHandler(event)" />
</s:Application>

You'll notice that the ActionScript in the scratch.MyFile.as is executed when the application is run.

You can use this method to include your drawing logic in your application. The external ActionScript is treated as if it were the method definitions for the class generated by the MXML.

Let me caution you before everyone jumps all over me. This is NOT a best practice. There are specific use-cases in which to use this feature of Flex. Before I get to them let me explain why your notion of keeping "logic" separate from your "view" is inaccurate.

Flex MXML files are not view-only code. They are a declarative dialect that simplifies ActionScript class definitions. When a Flex Project is compiled using mxmlc or compc (those are the compiler programs for flex applications and component libraries, respectively), MXML files are pre-compiled into ActionScript class definitions. If you add the -keep-generated-actionscript directive to your compiler options in Flash/Flex Builder/Ant/command line compile command, the compiler will leave the generated classes that compose the ActionScript class derived from the declaritive MXML files in your project. Thus, an MXML file becomes a class.

Having ActionScript defined in a Script block in your MXML is NOT mixing "logic" with "presentation". Likewise, MXML does NOT define the presentation of your project. It simply is a declarative subset of the ActionScript language that makes it easier to define presentation classes. As proof, you can define ArrayCollections, Strings, and Vectors in MXML. Those classes are data containers and have absolutely nothing to do with presentation.

Now, the reason putting all your ActionScript in external files is not a good thing is that it makes maintaining your project a headache. Not only does someone have to look up your component defined in MXML, but now they have to hunt through the codebase to find the script named Logic.as relatively defined to your component.

The use-cases in which including the external ActionScript via Script.source are the following:

  1. A group of predefined methods/properties are used in lots of components without change. Rather than copy-and-paste those methods into each component, you use the Script.source property to define the methods once and reference them throughout your application.
  2. Similar, but different from use-case-1: You require a mix-in. Like an interface, a mix-in is a set of methods that must be defined for the component to work, and those methods must be reusable and define explicit input parameters and output parameters. Unlike an interface, those methods can be of any namespace type: protected, final, public, internal, mx_internal, etc., and can must function bodies, i.e. have code inside the {} function block. For an example of a "mix-in" think of an enumerable object, an object that has next(), previous(), reset(), and iterator(), methods. When you want to iterate over the object's properties, you call iterator(), which returns an iterator object that calls next() and previous() to fetch the next and previous property values from the object. You can mix this functionality into all kinds of objects and use them usefully. Also, your included functionality is encapsuled within the classes in which it is included. It works like an include directive in AS3.

Hope this helps both your perceptions of what "logic" and "presentation" are in Flex, and helps you solve your particular issue.


I think you have it backwards. If you include the .as file into the .mxml using the <mx:script> tag, you will be able to see the function defined therein. To address the image, set it an id attribute. From that point, it becomes addressable as if it were defined using ActiveScript like

 var image:Image = new Image()


It is no very obvious what relations are between MXML and AS classes you're talking about but the simplest way is create public method in MXML which returns Image. Something like this:

…
<mx:Script>
<![CDATA[
public function getImage():Image
{
    return myImage;
}
]]>
</mx:Script>
<mx:Image id="myImage" />
…

So as far as you can refer to your MXML from AS you can call this method.


If you want to draw something in an image by using your own drawing class, i suggest you add it to the constructor of your drawing class, like so:

/*********************************************
* Variables
*********************************************/
private var _myImageIWantToDrawIn:Image;

/*********************************************
*   Properties
*********************************************/
public function set image(value:Image):void
{
    _myImageIWantToDrawIn = value;
}

public function get image():Image
{
    return _myImageIWantToDrawIn;
}

/*********************************************
* Constructor
*********************************************/
public function myDrawingclass(imageYouWantToDrawIn:Image)
{
    _myImageIWantToDrawIn = imageYouWantToDrawIn;   
}

like this, you can always access the image from that class and draw in it if you want to. (You can also access the _myImageIWantToDrawIn.graphics if you want to draw programmaticaly). you can add the properties if you want to change the image in runtime. you can then simply say: myDrawingclass.image = imageYouWantToDrawIn;

edit: this previous answer was actually the opposite of what you are asking, but I think this will do just fine for what you would want to do. If you want to access your as-class, just make an instance of your class and add public methods to it instead of private ones.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜