在侦听器中创建一个对象(一些 class)(第二部分)

To create an object (of some class) in a listener (part II)

我对此做了一些,反响很好,但尝试用听众举例我有一个错误:

是否有人会测试此代码并解释为什么找不到 EVENT_ONE class?

void functionONE(){
    result("\n dentro de la FUNCION ONE")
}


class EVENT_ONE : object{

    void accionONE(object self){
        result("\n dentro de accionONE()")
    }

    EVENT_ONE(object self) result("\n EVENT_ONE creado")
    ~EVENT_ONE(object self) result("\n EVENT_ONE destruido")
}

class KEY_TWO : object{

    number evento
    object o

    void almacenaEventoTWO(object self, number pulsacion) evento = pulsacion

    number accionTWO(object self, ImageDisplay disp, object keydesc){
        number control=0

        Result("\n key:"+keydesc.GetKeyDescriptor())
        Result(" ("+keydesc.GetDescription()+")") 

        If ( keydesc.MatchesKeyDescriptor("esc")){
            result("\n has pulsado escape")
            control=1
            disp.ImageDisplayRemoveKeyHandler(evento)

            o = alloc(EVENT_ONE)
            //number idObjecto2 = disp.ImageDisplayAddEventListener( o,     "accionONE" )
            o.accionONE()

        }
        return control
    }

    KEY_TWO(object self) result("\n KEY_TWO creado")
    ~KEY_TWO(object self) result("\n KEY_TWO destruido")
}


void main(){
    image img = getFrontImage()
    showimage(img)
    imageDisplay imgDisp = img.imageGetImageDisplay(0)

    object controlFinal = Alloc(KEY_TWO)
    number idControlFinal = imgDisp.ImageDisplayAddKeyHandler( controlFinal,     "accionTWO" )
    controlFinal.almacenaEventoTWO(idControlFinal)
}
main()

有必要将任何图像放在桌面上,以便按键侦听器 (class KEY_TWO) 工作。在这个class,当我按任意键时,打印它,如果你按"esc",销毁按键侦听器并找到错误("class EVENT_ONE not found")。

另一方面,是否可以从 class KEY_TWO 或 EVENT_ONE 调用 "functionONE"?

抱歉打扰了,我没发现错误。

感谢和问候。塞尔吉奥

Class 已执行 DM 脚本文件中的定义仅在该脚本执行期间有效。当用户为您的侦听器输入击键时,您的主要功能已完全执行完毕,因此 EVENT_ONE 的 class 定义不再有效。如果您将 EVENT_ONE 和 KEY_TWO class 的实现拆分到一个单独的文件中,然后将该文件安装为脚本库,您的代码将起作用。这样,class 定义在 DM 会话的整个生命周期内保持有效。

Mike 关于脚本代码保留 "available" 的说法是正确的,只要脚本解析器保留了这些代码。但是,更好的解决方案是在 constructor KEY_TWO class 中分配第二个对象(或在主脚本中调用的初始化方法中.) 在这个阶段,代码仍然可用。所以你上面的脚本变成了:

class EVENT_ONE : object{

    void accionONE(object self){
        result("\n dentro de accionONE()")
    }

    EVENT_ONE(object self) result("\n EVENT_ONE creado")
    ~EVENT_ONE(object self) result("\n EVENT_ONE destruido")
}

class KEY_TWO : object{

    number evento
    object o

    void almacenaEventoTWO(object self, number pulsacion){
        evento = pulsacion
    }

    number accionTWO(object self, ImageDisplay disp, object keydesc){
        number control=0

        Result("\n key:"+keydesc.GetKeyDescriptor())
        Result(" ("+keydesc.GetDescription()+")") 

        If ( keydesc.MatchesKeyDescriptor("esc")){
            result("\n has pulsado escape")
            control=1
            disp.ImageDisplayRemoveKeyHandler(evento)

            //o = alloc(EVENT_ONE)  // DO NOT ALLOCATE HERE - THE CODE IS NO LONGER AVAILABLE

            o.accionONE()
        }
        return control
    }

    KEY_TWO(object self) 
    {
        result("\n KEY_TWO creado")
        o = alloc(EVENT_ONE) // ALLOCATE HERE - THE CODE IS STILL AVAILABLE
    }
    ~KEY_TWO(object self) result("\n KEY_TWO destruido")

    // ALTERNATIVELY: Have a Init-method and alloacte here. This method is called (from the main script)
    // while all code is still available. Return the object self just to be able to "pipe-line" the Init call
    object Init(object self) {
        // o = alloc(EVENT_ONE) // ALTERNATIVE ALLOCATE HERE - THE CODE IS STILL AVAILABLE
        return self
    }
}


void main(){
    image img = getFrontImage()
    showimage(img)
    imageDisplay imgDisp = img.imageGetImageDisplay(0)

    object controlFinal = Alloc(KEY_TWO).Init() // Call INIT method
    number idControlFinal = imgDisp.ImageDisplayAddKeyHandler( controlFinal,     "accionTWO" )
    controlFinal.almacenaEventoTWO(idControlFinal)
}
main()

至于全局函数:我建议您完全避免 全局方法和变量。 OOC的思想是把所有的代码都封装在对象中。


最后,还有一个选项可以在main方法中分配所有对象,并将它们作为参数传递给其他对象。这允许f.e。让多个其他对象访问相同的对象。不过有一个警告:注意对象不能保存 "each other" 否则它们不能从内存中释放。 (这可以通过使用 ObjectID 和命令 GetScriptObjectFromID 来避免。请参阅 scripting->Objects[=27 一章中关于 weak referencing 的 F1 帮助文档=]了解更多信息。)

这种结构的一个例子:

class CCommon
{
    number v
    CCommon( object self ) { result("Created CCommon ID:"+self.ScriptObjectGetID()+"\n"); }
    ~CCommon( object self ) { result("Destructed CCommon ID:"+self.ScriptObjectGetID()+"\n"); }
    number GetV(object self ) { return v; }
    object SetV(object self, number val){ v=val; return self; }
}

class COne
{
    object co
    object init( object self, object common ) { co=common; return self; }
    object double( object self ) { co.SetV( co.GetV() * 2 ); return self; }
}

class CTwo
{
    object co
    object init( object self, object common ) { co=common; return self; }
    object AddOne( object self ) { co.SetV( co.GetV() + 1 ); return self; }
}

void main()
{
    object c = Alloc(CCommon).SetV(0)
    result("\n Initial:" + c.GetV() + "\n" )
    object o1 = Alloc(COne).Init(c)
    object o2 = Alloc(CTwo).Init(c)
    for (number i=0;i<10;i++)
    {
        o2.AddOne()
        result(" After +1: " + c.GetV() + "\n" )
        o1.Double()
        result(" After x2: " + c.GetV() + "\n" )
    }
}
main()