2

我对此做了一些其他问题,反应很好,但是尝试与听众一起举个例子我有一个错误:

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

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()

有必要将任何图像放在桌面上,以便按键侦听器(KEY_TWO 类)工作。在这堂课上,当我按任意键时,打印它,如果按“esc”,则销毁键侦听器并找到错误(“找不到类 EVENT_ONE”)。

另一方面,是否可以从 KEY_TWO 或 EVENT_ONE 类中调用“functionONE”?

很抱歉打扰,但我没有发现错误。

谢谢并恭祝安康。塞尔吉奥

4

2 回答 2

1

Mike 是正确的,脚本代码只有在脚本解析器持有时才保持“可用”。但是,解决问题的更好方法是在 KEY_TWO 类的构造函数中分配第二个对象(或在主脚本中调用的初始化方法中)。在这个阶段,代码仍然可用。所以你上面的脚本变成:

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 方法中分配所有对象并将它们作为参数传递给其他对象。这允许 fe 让多个其他对象访问相同的对象。但是有一个警告:注意对象不要“相互”持有,否则它们不能从内存中释放。(这可以通过使用 ObjectIDs 和 command 来避免。有关详细信息,请参阅章节scripting->Objects中有关弱引用GetScriptObjectFromID的 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()
于 2015-08-17T19:10:06.687 回答
0

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

于 2015-08-16T17:37:51.520 回答