Actionscript 3字典为刚刚在不同类中设置的键返回未定义/空

发布于 2024-08-15 17:23:38 字数 3594 浏览 1 评论 0原文

我根据给定的 XML 元素将显示对象渲染到舞台,如您在此处看到的:

PageRenderer.as

private static var curElements:Dictionary = new Dictionary();

//renders the current page
        private static function renderCode(pageCode:XML):void
        {

            if (pageCode)
            {
                //loop all elements from top to bottom
                for each (var child:XML in pageCode.descendants())
                {
                    var render:DisplayObject = ElementRenderer.render(child);
                    if (render)
                    {
                        WebBuilder.mainDisplay.addChild(render);
                        curElements[child] = render;    
                    }
                }   
            }
        }

因此,每个 XML 元素都有一个关联的渲染形状。如果您有 XML 元素,则可以像这样访问形状: var shape:DisplayObject = curElements[xmlElement];

这在同一个类中工作得很好。

然而,现在我还有 ElementSelector 类,它处理形状的选择并将形状完成的操作反映到 xml 元素。为此,需要在单击形状时获取 XML 元素:

ElementSelector.as

private static var currentSelection:XML;    

//fired when the stage has been clicked
            private static function stageClicked(event:MouseEvent):void
            {
                //if the element selector has been enabled
                if (enabled)
                {
                    var allPages:Array = CodeHandler.getPageCodes();
                    var mainElement:XML = allPages[CodeHandler.getCurPageId()];
                    var targetElement:XML = CodeHandler.getDeepestElementAtPos(mainElement, 0, event.stageX, event.stageY)["xml"];
                    if ((targetElement.localName() != "page") && (targetElement != currentSelection))
                    { //we have a new element selected
                        Utils.log("ElementSelector now selecting: " + targetElement.localName());
                        select(targetElement);
                    }
                    else if ((targetElement.localName() == "page") && (currentSelection))
                    { //the selection has been lost
                        Utils.log("ElementSelector now dropping selection.");
                        deselect();
                    }
                }
            }

            //sets the new selection
            private static function select(element:XML):void
            {
                if (currentSelection) deselect();
                currentSelection = element;

                var curElements:Dictionary = PageRenderer.getElements();
                var render:DisplayObject = curElements[element];
                trace(render);
            }

    //drops the current selection
            private static function deselect():void
            {
                currentSelection = null;
            }

我添加 StageClicked 事件函数只是为了让您了解我的过程是如何工作的。该功能本身运行良好。问题似乎出在 select() 方法中。

现在,奇怪的是,curElements[element] 返回 undefined 而 render 返回 null。

我尝试像这样调试它(在 select 方法的底部):

for (var key:Object in curElements) 
                {
                    if (key === element)
                    {
                        trace("key === element");
                    }
                                trace(curElements[key] === curElements[element]);
                    trace(curElements[key]);
                    trace(curElements[element]);
                }

它返回:

key === element
false
[object Shape]
undefined

为什么会发生这种情况?如果 a === b,那么 dic[a] === dic[b],对吗?嗯,显然不是。

所以,钥匙确实在那里……而且和它设置的钥匙是一样的。

为什么它不返回关联显示对象?

I'm rendering display objects to the stage depending on the given XML elements, as you can see here:

PageRenderer.as

private static var curElements:Dictionary = new Dictionary();

//renders the current page
        private static function renderCode(pageCode:XML):void
        {

            if (pageCode)
            {
                //loop all elements from top to bottom
                for each (var child:XML in pageCode.descendants())
                {
                    var render:DisplayObject = ElementRenderer.render(child);
                    if (render)
                    {
                        WebBuilder.mainDisplay.addChild(render);
                        curElements[child] = render;    
                    }
                }   
            }
        }

So, each XML element has an associative rendered shape. If you have the XML element, you can access the shape like this: var shape:DisplayObject = curElements[xmlElement];

This works fine within the same class.

However, now I also have the ElementSelector class which deals with selection of shapes and reflects the actions done with the shape to the xml element. To do this, one needs to get the XML element when the shape has been clicked:

ElementSelector.as

private static var currentSelection:XML;    

//fired when the stage has been clicked
            private static function stageClicked(event:MouseEvent):void
            {
                //if the element selector has been enabled
                if (enabled)
                {
                    var allPages:Array = CodeHandler.getPageCodes();
                    var mainElement:XML = allPages[CodeHandler.getCurPageId()];
                    var targetElement:XML = CodeHandler.getDeepestElementAtPos(mainElement, 0, event.stageX, event.stageY)["xml"];
                    if ((targetElement.localName() != "page") && (targetElement != currentSelection))
                    { //we have a new element selected
                        Utils.log("ElementSelector now selecting: " + targetElement.localName());
                        select(targetElement);
                    }
                    else if ((targetElement.localName() == "page") && (currentSelection))
                    { //the selection has been lost
                        Utils.log("ElementSelector now dropping selection.");
                        deselect();
                    }
                }
            }

            //sets the new selection
            private static function select(element:XML):void
            {
                if (currentSelection) deselect();
                currentSelection = element;

                var curElements:Dictionary = PageRenderer.getElements();
                var render:DisplayObject = curElements[element];
                trace(render);
            }

    //drops the current selection
            private static function deselect():void
            {
                currentSelection = null;
            }

I added the StageClicked event function only so you have an idea of how my procedure works. That function itself works fine. The problem seems to lie within the select() method.

Now, the strange thing is, that curElements[element] returns undefined and render returns null.

I tried to debug it like this (at bottom of select method):

for (var key:Object in curElements) 
                {
                    if (key === element)
                    {
                        trace("key === element");
                    }
                                trace(curElements[key] === curElements[element]);
                    trace(curElements[key]);
                    trace(curElements[element]);
                }

It returns:

key === element
false
[object Shape]
undefined

Why is this happening? If a === b, then dic[a] === dic[b], right? Well, apparently not.

So, the key really is there... and it's the same as the key it was set with.

Why isn't it returning the associative display object?

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

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

发布评论

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

评论(2

新一帅帅 2024-08-22 17:23:38

如果这没有帮助,我很抱歉,但我认为您构建应用程序的方式(使用 XML 对象作为字典键)从一开始就有缺陷。我强烈建议使用其他方法来索引元素,例如在 XML 中使用用于键的 id 属性。或者您可以简单地使用递增的整数索引。

另一种选择是为 ElementRenderer.render() 返回的对象创建一个类(或接口),并将您的 ID 作为该接口中的属性:

public interface IRenderedElement
{
  function get id() : String;
}

然后您可以将元素存储在平面数组或 Vector 中。

如果您使用 XML 节点的原因是您需要存储在 XML 中声明的数据,那么我强烈建议您解析 XML 并将数据存储在自定义 Element 类中,而不是弱类型内部,动态XML对象。上述接口是放置此类数据属性的好方法。

如果您需要做的只是查找单击了哪个元素,那么我建议向所有元素添加事件侦听器,并使用 Event.currentTarget 属性来标识该元素。

var element:DisplayObject = ElementRenderer.render(child);
render.addEventListener(MouseEvent.CLICK, handleElementClick);

/* ... */

function handleElementClick(ev : MouseEvent) : void
{
  var element : IRenderedElement = ev.currentTarget as IRenderedElement;

  // do something here
}

您还可以简单地侦听所有元素的父元素,即 WebBuilder.mainDisplay,然后使用 Event.target 属性来查找被单击的确切对象。

I'm sorry if this doesn't help, but I think that the way you've constructed your application, using XML objects as dictionary keys, is flawed in the first place. I would greatly suggest having some other way to index the elements, such as having an id attribute in the XML that is used for the key. Or you could simply use an incremented integer index.

Another option would be to create a class (or interface) for the objects returned by ElementRenderer.render(), and have your ID as a property in that interface:

public interface IRenderedElement
{
  function get id() : String;
}

You could then store your elements in a flat array or Vector.

If the reason you are using the XML nodes is that you need to store the data that is declared in the XML, then I would strongly suggest that you parse the XML and store the data in a custom Element class instead of inside the weakly-typed, dynamic XML object. The above interface would be a good way to place properties for such data.

If all you need to do is find which element was clicked, then I would suggest adding event listeners to all of the elements, and using the Event.currentTarget property to identify the element.

var element:DisplayObject = ElementRenderer.render(child);
render.addEventListener(MouseEvent.CLICK, handleElementClick);

/* ... */

function handleElementClick(ev : MouseEvent) : void
{
  var element : IRenderedElement = ev.currentTarget as IRenderedElement;

  // do something here
}

You could also simply listen on the parent of all the elements, i.e. WebBuilder.mainDisplay, and then use the Event.target property to find the exact object that was clicked.

陈甜 2024-08-22 17:23:38

字典 使用严格相等 (===)非原始对象键的键比较。因此 key == elements 可能会返回 true,但在您的情况下 key === elemets 将返回 false。由于元素和键对象不同。
尝试使用关联数组而不是字典。

Dictionary uses strict equality (===) for key comparison on non-primitive object keys. So key == elements might return true but key === elemets will be returning false in your case. As element and key object are different.
Try using associative array instead of Dictionary.

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