【问题标题】:Getting child targets for mouse click event in OpenFL在 OpenFL 中获取鼠标单击事件的子目标
【发布时间】:2017-08-17 21:40:39
【问题描述】:

我有一个包含多个不同类型的子对象的阶段。我在舞台上有一个事件监听器。我想通过鼠标点击获得目标子对象,这样我就可以处理不同对象类型的点击。

类似的东西:

stage.addEventListener(MouseEvent.CLICK, onClick);

function onClick(e:Event):Void
{
    var target = e.target
    // if target type is Foo
    //     target.aFooMethod();
    // else if target type is Bar
    //     target.aBarMethod();

}

这样做的正确方法是什么?跟踪 e.target 似乎打印了正确的对象类型,但我无法调用任何对象方法。

我隐约记得在 actionscript 3 中能够使用 target.name 但在这种情况下返回 null。

【问题讨论】:

    标签: types mouseevent haxe rtti openfl


    【解决方案1】:

    听起来您的问题主要是关于运行时类型识别 (RTTI) 和类型转换。 Haxe 在TypeReflect 类中提供了许多实用程序来处理这个问题。

    对于您的代码,您似乎特别想要:

    if (Std.is(target, Foo)) (cast target:Foo).aFooMethod();
    else if (Std.is(target, Bar)) (cast target:Bar).aBarMethod();
    

    或许:

    if (Std.is(target, Foo)) {
      var targetAsFoo:Foo = cast target;
      targetAsFoo.aFooMethod();
    } else if (Std.is(target, Bar)) {
      var targetAsBar:Bar = cast target;
      targetAsBar.aBarMethod();
    }
    

    这是一个示例,展示了许多可以帮助您的实用程序,包括Std.is、接口、Type.getClass、类型转换等:http://try.haxe.org/#3C192

    代码如下:

    class Test {
        static function main() {
     
            function identify(tgt:Dynamic)
            {
                trace("1: "+tgt);
                trace("2: "+Type.typeof(tgt));
                trace("3: "+Type.getClassName(tgt));
                trace("4: "+Type.getClass(Type.getClassName(tgt)));
                trace("5: "+Std.is(tgt, Something));
     
                if (Std.is(tgt, Something)) {
                // Can cast explicitly
                    var casted:Something = cast tgt;
                    trace("Got a Something named: "+casted.name);
                }
     
                if (Std.is(tgt, Something)) {
                // Can cast implicitly
                    var casted:Something = untyped tgt;
                    trace("Got a Something named: "+casted.name);
                }
     
                if (Std.is(tgt, Something)) {
                // Can cast in an inline style, (obj:Type)
                    trace("Got a Something named: "+(tgt:Something).name);
                }
     
                if (Std.is(tgt, IHasAName)) {
                // Can cast to an interface, if you prefer
                    var i_casted:IHasAName = (tgt:IHasAName);
                    trace("Got a IHasAName named: "+i_casted.name);
                }
     
                // Can reflect to see if the name field exists:
                if (Reflect.hasField(tgt, "name")) {
                    trace("tgt has a name: "+Reflect.field(tgt, "name"));
                }
                if (Reflect.hasField(tgt, "length")) {
                    trace("tgt has a length: "+Reflect.field(tgt, "length"));
                }
            }
            
            trace("----------------------------------");
            trace("Calling identify with a Something:");
            trace("----------------------------------");
            var a = new Something("foo", 3);
            identify(a);
     
            trace("----------------------------------");
            trace("Calling identify with a String:");
            trace("----------------------------------");
            var b = "a string";
            identify(b);
     
            trace("----------------------------------");
            trace("Calling identify with anonymous:");
            trace("----------------------------------");
            var c =  { "name" : "anonymous" };
            identify(c);
     
        }
    }
     
    class Something implements IHasAName
    {
        public var name:String;
        public var length:Int;
        public function new(name:String, length:Int)
        {
            this.name = name;
            this.length = length;
        }
    }
     
    interface IHasAName {
        public var name:String;
    }
    

    输出是:

    14:41:24:664   ----------------------------------
    14:41:24:664   Calling identify with a Something:
    14:41:24:664   ----------------------------------
    14:41:24:664   1: { name : foo, length : 3 }
    14:41:24:665   2: TClass({ __name__ : [Something] })
    14:41:24:665   3: null
    14:41:24:665   4: null
    14:41:24:665   5: true
    14:41:24:665   Got a Something named: foo
    14:41:24:665   Got a Something named: foo
    14:41:24:665   Got a Something named: foo
    14:41:24:665   Got a IHasAName named: foo
    14:41:24:665   tgt has a name: foo
    14:41:24:665   tgt has a length: 3
    14:41:24:666   ----------------------------------
    14:41:24:666   Calling identify with a String:
    14:41:24:666   ----------------------------------
    14:41:24:666   1: a string
    14:41:24:666   2: TClass({ __name__ : [String] })
    14:41:24:666   3: null
    14:41:24:666   4: null
    14:41:24:666   5: false
    14:41:24:666   tgt has a length: 8
    14:41:24:667   ----------------------------------
    14:41:24:667   Calling identify with anonymous:
    14:41:24:667   ----------------------------------
    14:41:24:667   1: { name : anonymous }
    14:41:24:667   2: TObject
    14:41:24:667   3: null
    14:41:24:668   4: null
    14:41:24:668   5: false
    14:41:24:668   tgt has a name: anonymous
    

    我隐约记得在 actionscript 3 中能够使用 target.name 但在这种情况下返回 null。

    在 AS3 中,event.target 的类型为 DisplayObject,而所有 DisplayObjects have a .name property,这就是您可以在 AS3 中这样做的原因。

    OpenFL 的 Event.target 是一个 IEventDispatcher,它与显示类没有特别关联。

    【讨论】:

      【解决方案2】:

      您确定您的舞台具有“名称”值吗? 根据我的测试,使用 event.target.name 应该可以。

      要确认,请尝试使用event.target.id,因为即使未手动指定,框架也会设置默认值。

      祝你好运。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-16
        相关资源
        最近更新 更多