【问题标题】:Yet another Flex custom events in components question组件问题中的另一个 Flex 自定义事件
【发布时间】:2011-02-03 22:36:40
【问题描述】:

我似乎无法获得在 Flex 4 中工作的事件的最基本用途之一。我已经学习了多个教程并到处查看。据我所知,我做的一切都是正确的,所以一定有什么愚蠢的错误。

我有一个包含按钮的主应用程序文件。单击按钮时,它会触发一个自定义事件,我希望我的子组件中的侦听器能够捕获该事件。事件正在触发。子组件事件侦听器未捕获该事件。不知道为什么。自定义事件是从 Adobe's tutorial 复制粘贴的(减去自定义命名空间和 cmets)。

主要应用

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                       xmlns:s="library://ns.adobe.com/flex/spark" 
                       xmlns:mx="library://ns.adobe.com/flex/mx"
                       applicationComplete="init()" xmlns:local="*">
    <fx:Metadata>
        [Event(name="enableChanged", type="EnableChangeEvent")]
    </fx:Metadata>

    <fx:Script>
        <![CDATA[
            import EnableChangeEvent;
            import TestComponent;

            private function doDispatchEvent(event:MouseEvent):void {
                if(dispatchEvent(new EnableChangeEvent(EnableChangeEvent.ENABLE_CHANGED, true)))
                {
                    statusLabel.text = "Event was dispatched";
                }
            }

            public function init():void {
                myButton.addEventListener(MouseEvent.CLICK, doDispatchEvent);
            }
        ]]>
    </fx:Script>

    <s:Button x="95" y="83" label="Button" id="myButton" />
    <s:Label x="230" y="83" text="" id="statusLabel" />
    <local:TestComponent x="95" y="150" width="300" height="400" />
</s:WindowedApplication>

子组件(测试)

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
         xmlns:s="library://ns.adobe.com/flex/spark" 
         xmlns:mx="library://ns.adobe.com/flex/mx"
         width="100%" height="100%"
         initialize="init();">

    <fx:Script>
        <![CDATA[
            import EnableChangeEvent;

            private function doFinalAction(event:EnableChangeEvent):void {
                myLabel.text = "Custom Event Recieved";
            }

            private function init():void {
                addEventListener(EnableChangeEvent.ENABLE_CHANGED, doFinalAction);
            }
        ]]>
    </fx:Script>

    <s:Label width="300" height="50" text="Should change on click" id="myLabel" />
</s:Group>

自定义事件(来自 Adob​​e)

package {
    import flash.events.Event;

    public class EnableChangeEvent extends Event
    {
        public function EnableChangeEvent(type:String, isEnabled:Boolean=false) {
            super(type);
            this.isEnabled = isEnabled;
        }

        public static const ENABLE_CHANGED:String = "enableChanged";
        public var isEnabled:Boolean;

        override public function clone():Event {
            return new EnableChangeEvent(type, isEnabled);
        }
    }
}

【问题讨论】:

    标签: apache-flex events flex4 custom-component


    【解决方案1】:

    Timofei Davydik 的回答是正确的。由于Application 对象调度事件,如果您希望TestComponent 对象捕获它,您必须从TestComponent 中添加一个侦听器到Application 对象的引用。您可以使用TestComponent 对象的继承属性“parentApplication”来获取对Application 对象的引用。

    在TestComponent.mxml中修改如下代码:

    private function init():void 
    {     
        this.parentApplication.addEventListener(EnableChangeEvent.ENABLE_CHANGED, doFinalAction);  
    
    }// end function 
    

    [更新]

    我个人觉得你使用事件的方式不对,所以我制作了一个类似的 flex 应用程序来演示如何在 flex 中使用事件。

    Main.mxml

    <?xml version="1.0" encoding="utf-8"?>
    
    <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                           xmlns:s="library://ns.adobe.com/flex/spark" 
                           xmlns:mx="library://ns.adobe.com/flex/mx"
                           xmlns:components="components.*"
                           xmlns:events="events.*"
                           applicationComplete="init()">
    
        <fx:Script>
            <![CDATA[
    
                import events.EnableChangeEvent;
    
                public function init():void
                {     
                    label1.text = "Application Complete!";
    
                }// end function
    
                private function onTestButtonEnableChanged(e:EnableChangeEvent):void
                {                     
                    label2.text = "Enabled = " + e.isEnabled;   
    
                }// end function
    
            ]]>
        </fx:Script>
    
        <s:layout>
            <s:VerticalLayout horizontalAlign="center" paddingTop="50" />
        </s:layout>
    
        <components:TestButton id="testButton" label="CLICK!" enableChanged="onTestButtonEnableChanged(event)"  />
        <s:Label id="label1"/> 
        <s:Label id="label2"/>
    
    </s:WindowedApplication>
    

    TestButton.mxml

    <?xml version="1.0" encoding="utf-8"?>
    
    <s:Button xmlns:fx="http://ns.adobe.com/mxml/2009" 
              xmlns:s="library://ns.adobe.com/flex/spark" 
              xmlns:mx="library://ns.adobe.com/flex/mx"
              click="onClick()">
    
        <fx:Metadata>
            [Event(name="enableChanged", type="events.EnableChangeEvent")]
        </fx:Metadata>
    
        <fx:Script>
    
            <![CDATA[
    
                import events.EnableChangeEvent
    
                private var isEnabled:Boolean;
    
                private function onClick():void
                {
                    isEnabled = !isEnabled;
    
                    dispatchEvent(new EnableChangeEvent(EnableChangeEvent.ENABLE_CHANGED, isEnabled));
    
                }// end function
    
            ]]>
    
        </fx:Script>
    
    </s:Button>
    

    应用程序之间的主要区别在于Button 对象(在本例中为TestButton 对象)在单击时调度EnableChangeEvent 事件。在调度事件时,我们可以将TestButton_isEnabled 属性的布尔值解析为事件。之前,使用isEnabled = !isEnabled 行反转该值。现在我们可以使用带有xml属性enableChangedTestButton对象的mxml声明来处理事件。

    另外,您可能想尝试一本我正在阅读的书,而不是遵循教程。它被 David Gassner 称为“Adobe Flash Builder 4 和 Flex 4 Bible”,您可以将其作为平装书或 Kindle 书籍。

    【讨论】:

    • 如果我正确理解您更新的解决方案,这与我需要做的相反,即子管理自己以响应父级(或在这种情况下,应用程序本身)的变化.我正在编写一个小型窗口管理系统,其中应用程序包含窗口,每个窗口都会更新自己以响应诸如调整应用程序窗口大小之类的事情。您提供的解决方案具有负责调整所有窗口大小的全局应用程序。
    • 进一步考虑,您可能是正确的,即拥有一个纯粹的层次结构,其中孩子对父母一无所知。然而,现在,让孩子知道关于父母的一件事更加紧凑和有效,因此我不必编写单独的子管理器对象来坐在应用程序和孩子之间。这个人为的例子并没有说明为什么我需要这样安排我的程序。无论哪种方式,将事件侦听器应用于父级都有效,谢谢!
    【解决方案2】:

    @Taurayi 是正确的,但要让您当前的代码只需进行一项更改,请将测试组件的 init 编辑为如下所示:

    private function init():void 
    { 
         FlexGlobals.topLevelApplication.addEventListener(EnableChangeEvent.ENABLE_CHANGED, doFinalAction);
    }
    

    【讨论】:

    • 您的意思是使用parentApplication 不正确还是使用FlexGlobals.topLevelApplication 是更好的选择。我还在学习 Flex,所以如果你能解释一下它会对我有所帮助。
    • FlexGlobals 指的是顶级应用程序。使用 parentApplication 可能会为嵌入式 swf 提供参考(如果您使用任何)。据我所知,FlexGlobals 是 Fl​​ex 4 的最佳实践方法
    • 感谢您为我澄清,我想知道有什么区别,因为它们看起来都是一样的。
    【解决方案3】:

    您的应用程序对象调度自定义事件。为什么你希望你的团队“抓住”这个事件?它不会。自定义事件既没有捕获阶段也没有冒泡阶段。因此,只有添加到您的应用程序对象的侦听器才会侦听此事件。

    【讨论】:

    • 仅供参考 - 显示列表上的对象调度的自定义事件可以冒泡。
    • 自定义事件可以像任何其他事件一样冒泡到应用程序级别,只需正确设置您的事件:blogagic.com/133/…
    • 我错了,对不起。 Event构造函数中的“bubbles”参数默认为false。
    • 还有一个事实是,作为基于事件的编程的新手,我假设事件全局应用于具有兼容侦听器的所有对象,无论它们在应用程序中的位置如何(侦听器表和表例如,每帧都会检查的可能事件数)。
    猜你喜欢
    • 2010-11-14
    • 2011-04-11
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    • 2012-03-20
    • 1970-01-01
    • 2010-10-23
    • 2011-04-01
    相关资源
    最近更新 更多