在 OpenFL 中获取鼠标单击事件的子目标

Getting child targets for mouse click event in OpenFL

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

大致如下:

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 但在这种情况下 return null。

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

对于你的代码,看起来你特别想要:

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

I vaguely remember in actionscript 3 being able to use target.name but return null in this case.

在 AS3 中,event.targetDisplayObject 类型,并且都是 DisplayObjects have a .name property,这就是您可以在 AS3 中这样做的原因。

OpenFL 的 Event.target is an IEventDispatcher,它与显示没有特别关联 类。

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

要确认,请尝试使用 event.target.id,因为框架会设置一个默认值,即使它不是手动指定的。

祝你好运。