Flex 树控件 - 如何通过 URL 引用图标?

发布于 2024-08-26 17:02:17 字数 307 浏览 4 评论 0原文

我有一个对象集合,这些对象显示在两个位置 - 空间上作为地图上的图标,以及在树控件中。我想知道是否可以使用用于在树控件中其他位置显示图标的图像 URL。

我尝试简单地使用包含 URL 的字段名称作为树控件上的 iconField,但显然,当 Flex 框架将字符串字段视为图标字段时,它会在包含以下内容的 mxml 文件上查找属性:树的名称与树项上字段的字符串值相同(!?!)。由于我的布局文档没有任何名称类似于“assets/well.png”的字段,因此这会引发错误。

我需要使用图像的 URL 而不是通过嵌入来引用图标,因为客户端需要能够更改图像而无需重新编译。

I have a collection of objects that are displayed in two places - spatially as icons on a map, and in a tree control. I'd like to know if it's possible to use the image URLs that I use for displaying the icons elsewhere in a tree control.

I've tried simply using the name of the field that contains the URL as the iconField on the tree control, but apparently when the flex framework sees a string field as the icon field it looks for a property on the mxml file containing the tree with a name that's the same as the string value for the field on the tree item(!?!). Since my layout documents don't have any fields with names like "assets/well.png", this throws an error.

I need to reference the icons using the URL of the images rather than through embedding, because the client will need to be able to change the image without a recompile.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光病人 2024-09-02 17:02:17

Tree setItemIcon 函数(或 itemIcons 属性)采用两个 Class 对象作为参数。
一种可能的解决方案是将 此类 添加到您的项目中,然后使用以下命令动态加载资源的代码:

yourTree.itemIcons = {iconID: IconUtility.getClass(icon1, 'path/icon1.jpg'), iconID2: IconUtility.getClass(icon2, 'path/icon2.jpg')};

编辑:
关于 IconUtility 类的原始帖子:http://blog.benstucki.net/?p=42

Tree setItemIcon function (or itemIcons property) takes two Class objects as parameters.
A possible solution would be to add this class to your project, and then use the following code to dynamically load your assets:

yourTree.itemIcons = {iconID: IconUtility.getClass(icon1, 'path/icon1.jpg'), iconID2: IconUtility.getClass(icon2, 'path/icon2.jpg')};

Edit:
Original post about the IconUtility class : http://blog.benstucki.net/?p=42

感性 2024-09-02 17:02:17

我尝试构建一个完整的工作示例,并想在这里分享我的经验。这是我的测试代码:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
            layout="vertical"
            verticalAlign="middle"
            backgroundColor="white">

<mx:Script>
    <![CDATA[
    import mx.controls.listClasses.IListItemRenderer;

    private function tree_iconFunc(item:Object):Class
    {
        var iconClass:Class;
        var renderer:IListItemRenderer = myTree.itemToItemRenderer(item);
        switch (XML(item)[email protected]().charAt(0))
        {
            case "B":
                iconClass = IconUtility.getClass(renderer, 'http://onair.adobe.com/images/lynch.jpg', 16, 16);
                break;
            case "C":
                iconClass = IconUtility.getClass(renderer, 'http://onair.adobe.com/images/downey.jpg', 16, 16);
                break;
            case "K":
                iconClass = IconUtility.getClass(renderer, 'http://onair.adobe.com/images/mesh.jpg', 16, 16);
                break;
        }

        return iconClass;
    }
    ]]>
</mx:Script>

<mx:XML id="dp">
    <mlb>
        <league label="American League">
            <division label="East">
                <team label="Boston"/>
                <team label="New York"/>
                <team label="Toronto"/>
                <team label="Baltimore"/>
                <team label="Tampa Bay"/>
            </division>
            <division label="Central">
                <team label="Cleveland"/>
                <team label="Detroit"/>
                <team label="Minnesota"/>
                <team label="Chicago"/>
                <team label="Kansas City"/>
            </division>
            <division label="West">
                <team label="Los Angeles"/>
                <team label="Seattle"/>
                <team label="Oakland"/>
                <team label="Texas"/>
            </division>
        </league>
    </mlb>
</mx:XML>

<mx:Tree id="myTree"
         dataProvider="{dp.league}"
         labelField="@label"
         showRoot="true"
         iconFunction="tree_iconFunc"
         fontSize="12"
         width="500"
         height="400"/>

</mx:Application>

它基于以下示例: http://blog.flexexamples.com/2007/11/15/creating-a-custom-icon-function-on-a-flex-tree-control/

这是我使用的 IconUtility 类:

package
{
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.geom.Matrix;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.utils.Dictionary;

import mx.containers.accordionClasses.AccordionHeader;
import mx.controls.tabBarClasses.Tab;
import mx.core.BitmapAsset;
import mx.core.UIComponent;

/**
 * Provides a workaround for using run-time loaded graphics in styles and properties which require a Class reference
 */
public class IconUtility extends BitmapAsset
{

    private static var dictionary:Dictionary;

    /**
     * Used to associate run-time graphics with a target
     * @param target A reference to the component associated with this icon
     * @param source A url to a JPG, PNG or GIF file you wish to be loaded and displayed
     * @param width Defines the width of the graphic when displayed
     * @param height Defines the height of the graphic when displayed
     * @return A reference to the IconUtility class which may be treated as a BitmapAsset
     * @example <mx:Button id="button" icon="{IconUtility.getClass(button, 'http://www.yourdomain.com/images/test.jpg')}" />
     */
    public static function getClass( target:*, source:String, width:Number = NaN, height:Number = NaN ):Class {
        if(!dictionary) {
            dictionary = new Dictionary(false);
        }
        //if(source is String) {
            var loader:Loader = new Loader();
            loader.load(new URLRequest(source as String), new LoaderContext(true));
            //source = loader;
        //}
        dictionary[target] = { source:loader, width:width, height:height };

        return IconUtility;
    }

    /**
     * @private
     */
    public function IconUtility():void {
        addEventListener(Event.ADDED, addedHandler, false, 0, true)
    }

    private function addedHandler(event:Event):void {
        if(parent) {
            if(parent is AccordionHeader) {
                var header:AccordionHeader = parent as AccordionHeader;
                getData(header.data);
            } else if(parent is Tab) {
                var tab:Tab = parent as Tab;
                getData(tab.data);
            } else {
                getData(parent);
            }
        }
    }

    private function getData(object:Object):void {
        var data:Object = dictionary[object];
        if(data) {
            var source:Object = data.source;
            if(data.width > 0 && data.height > 0) {
                bitmapData = new BitmapData(data.width, data.height, true, 0x00FFFFFF);
            }
            if(source is Loader) {
                var loader:Loader = source as Loader;
                if(!loader.content) {
                    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler, false, 0, true);
                } else {
                    displayLoader(loader);
                }
            }
        }
    }

    private function displayLoader( loader:Loader ):void {
        if(!bitmapData) {
            bitmapData = new BitmapData(loader.content.width, loader.content.height, true, 0x00FFFFFF);
        }
        bitmapData.draw(loader, new Matrix(bitmapData.width/loader.width, 0, 0, bitmapData.height/loader.height, 0, 0));
        if(parent is UIComponent) {
            var component:UIComponent = parent as UIComponent;
            component.invalidateSize();
        }
    }

    private function completeHandler(event:Event):void {
        if(event && event.target && event.target is LoaderInfo) {
            displayLoader(event.target.loader as Loader);
        }
    }

}
}

这是来自 Ben 的完整副本Stucki,除了 getClass 函数的 target 参数,我将类型从 UIComponent 更改为 * 如此博客的评论中所建议。

剩下的问题:

  1. 图标闪烁: 如果您打开和/或关闭分支,则会出现大量闪烁。 (在 Firefox 3 和 flashplayer 10.2 上测试)
  2. 如果您第一次打开分支,当图标加载时,您会看到树中的文本“跳”到右侧。
  3. 在我的“真实”程序中,图标似乎仅在我打开时才会出现。将鼠标悬停在树节点上,当我打开另一个分支时也会消失。我无法在我的简单测试程序中重现这一点,但这显然是一个问题,因为其他 也报告了这个问题。

如果有人能够阐明这些问题以及如何解决它们,我将不胜感激。

I tried to build a complete working example and want to share my experience here. This is my test code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
            layout="vertical"
            verticalAlign="middle"
            backgroundColor="white">

<mx:Script>
    <![CDATA[
    import mx.controls.listClasses.IListItemRenderer;

    private function tree_iconFunc(item:Object):Class
    {
        var iconClass:Class;
        var renderer:IListItemRenderer = myTree.itemToItemRenderer(item);
        switch (XML(item)[email protected]().charAt(0))
        {
            case "B":
                iconClass = IconUtility.getClass(renderer, 'http://onair.adobe.com/images/lynch.jpg', 16, 16);
                break;
            case "C":
                iconClass = IconUtility.getClass(renderer, 'http://onair.adobe.com/images/downey.jpg', 16, 16);
                break;
            case "K":
                iconClass = IconUtility.getClass(renderer, 'http://onair.adobe.com/images/mesh.jpg', 16, 16);
                break;
        }

        return iconClass;
    }
    ]]>
</mx:Script>

<mx:XML id="dp">
    <mlb>
        <league label="American League">
            <division label="East">
                <team label="Boston"/>
                <team label="New York"/>
                <team label="Toronto"/>
                <team label="Baltimore"/>
                <team label="Tampa Bay"/>
            </division>
            <division label="Central">
                <team label="Cleveland"/>
                <team label="Detroit"/>
                <team label="Minnesota"/>
                <team label="Chicago"/>
                <team label="Kansas City"/>
            </division>
            <division label="West">
                <team label="Los Angeles"/>
                <team label="Seattle"/>
                <team label="Oakland"/>
                <team label="Texas"/>
            </division>
        </league>
    </mlb>
</mx:XML>

<mx:Tree id="myTree"
         dataProvider="{dp.league}"
         labelField="@label"
         showRoot="true"
         iconFunction="tree_iconFunc"
         fontSize="12"
         width="500"
         height="400"/>

</mx:Application>

It is based on this example: http://blog.flexexamples.com/2007/11/15/creating-a-custom-icon-function-on-a-flex-tree-control/

This is the IconUtility class I use with it:

package
{
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.geom.Matrix;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.utils.Dictionary;

import mx.containers.accordionClasses.AccordionHeader;
import mx.controls.tabBarClasses.Tab;
import mx.core.BitmapAsset;
import mx.core.UIComponent;

/**
 * Provides a workaround for using run-time loaded graphics in styles and properties which require a Class reference
 */
public class IconUtility extends BitmapAsset
{

    private static var dictionary:Dictionary;

    /**
     * Used to associate run-time graphics with a target
     * @param target A reference to the component associated with this icon
     * @param source A url to a JPG, PNG or GIF file you wish to be loaded and displayed
     * @param width Defines the width of the graphic when displayed
     * @param height Defines the height of the graphic when displayed
     * @return A reference to the IconUtility class which may be treated as a BitmapAsset
     * @example <mx:Button id="button" icon="{IconUtility.getClass(button, 'http://www.yourdomain.com/images/test.jpg')}" />
     */
    public static function getClass( target:*, source:String, width:Number = NaN, height:Number = NaN ):Class {
        if(!dictionary) {
            dictionary = new Dictionary(false);
        }
        //if(source is String) {
            var loader:Loader = new Loader();
            loader.load(new URLRequest(source as String), new LoaderContext(true));
            //source = loader;
        //}
        dictionary[target] = { source:loader, width:width, height:height };

        return IconUtility;
    }

    /**
     * @private
     */
    public function IconUtility():void {
        addEventListener(Event.ADDED, addedHandler, false, 0, true)
    }

    private function addedHandler(event:Event):void {
        if(parent) {
            if(parent is AccordionHeader) {
                var header:AccordionHeader = parent as AccordionHeader;
                getData(header.data);
            } else if(parent is Tab) {
                var tab:Tab = parent as Tab;
                getData(tab.data);
            } else {
                getData(parent);
            }
        }
    }

    private function getData(object:Object):void {
        var data:Object = dictionary[object];
        if(data) {
            var source:Object = data.source;
            if(data.width > 0 && data.height > 0) {
                bitmapData = new BitmapData(data.width, data.height, true, 0x00FFFFFF);
            }
            if(source is Loader) {
                var loader:Loader = source as Loader;
                if(!loader.content) {
                    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler, false, 0, true);
                } else {
                    displayLoader(loader);
                }
            }
        }
    }

    private function displayLoader( loader:Loader ):void {
        if(!bitmapData) {
            bitmapData = new BitmapData(loader.content.width, loader.content.height, true, 0x00FFFFFF);
        }
        bitmapData.draw(loader, new Matrix(bitmapData.width/loader.width, 0, 0, bitmapData.height/loader.height, 0, 0));
        if(parent is UIComponent) {
            var component:UIComponent = parent as UIComponent;
            component.invalidateSize();
        }
    }

    private function completeHandler(event:Event):void {
        if(event && event.target && event.target is LoaderInfo) {
            displayLoader(event.target.loader as Loader);
        }
    }

}
}

This is complete copy from Ben Stucki, except for the target argument of the getClass function where I changed the type from UIComponent to * as adviced in the comments of this blog.

Problems left:

  1. Icons flicker: There is a lot of flickering going on if you open and/or close branches. (Tested on Firefox 3 and flashplayer 10.2)
  2. You see the text in the tree 'jump' to the right when the icons load if you open a branch for the first time
  3. In my "real" program, the icon seems to only appear when I mouse over the tree node and also disappears when I open another branch. I was unable to reproduce this in my simple test program, but it is clearly a problem since others have also reported that problem.

I would be most grateful if somebody could shed some light on those issues and how to fix them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文