在Corona sdk中创建一个类并从中调度事件?

时间:2014-01-26 13:15:50

标签: oop lua corona

我想创建一个类,当按下按钮时,它会从这个类中保存一些图形和调度事件......这是我的简单代码:

MyClass.lua:

local Class = {}
local Class_mt = { __index = Class }    -- metatable
local thisObject

-------------------------------------------------
-- PRIVATE FUNCTIONS
-------------------------------------------------

local function tapListener( e )    -- local; only visible in this module
    local event = {
        name = "customEvent",
        mycustomvar = "this is my custom var"
    }

    thisObject.body:dispatchEvent( event )
end

-------------------------------------------------
-- PUBLIC FUNCTIONS
-------------------------------------------------

function Class.new( )    -- constructor

    local rect = display.newRect( 0, 0, 50, 50 )
    rect:addEventListener( "tap", tapListener )

    local newClass = {
        body = rect
    }

    return setmetatable( newClass, Class_mt )
end


-- added this function to get reference to the object
function Class:init()
    thisObject = self
end
-------------------------------------------------

return Class

然后创建这个类并听取一些被调度的事件:

local MyClass = require( "MyClass" )

function myCustomEvent(e)
  print(e.mycustomvar)
end

local myNewClass = MyClass.new()
myNewClass:init()
myNewClass.body:addEventListener("customEvent", myCustomEvent)

这确实有用......但是看起来有点hacky - 请告诉我你的想法?

感谢。

2 个答案:

答案 0 :(得分:1)

我查看了代码。现在应该可以了。

MyClass.lua:

local Class = {}
local Class_mt = { __index = Class }    -- metatable

-------------------------------------------------
-- PRIVATE FUNCTIONS
-------------------------------------------------


local function tapListener( e )    -- local; only visible in this module
    local event = {
        name = "customEvent",
        myscustomvar = "this is my custom var"
    }
    Runtime:dispatchEvent( event )
end

-------------------------------------------------
-- PUBLIC FUNCTIONS
-------------------------------------------------

function Class.new( )    -- constructor

    local rect = display.newRect( 0, 0, 50, 50 )
    rect:addEventListener( "tap", tapListener )


    local newClass = {
        body = rect
    }

    return setmetatable( newClass, Class_mt )
end

-------------------------------------------------

return Class

main.lua

local MyClass = require( "MyClass" )
local mynewclass = MyClass.new()

local function myCustomEvent(e)
    print(e.myscustomvar)
end

Runtime:addEventListener("customEvent", myCustomEvent)

答案 1 :(得分:1)

http://docs.coronalabs.com/api/type/EventListener/dispatchEvent.html所述,dispatchEvent是显示对象的方法。所以你不能在你的Class上调用它,因为class只是一个表示“Class”类的表(你应该把它命名为其他东西;)所以你要在rect上调用dispatchEvent(如果它代表一个自定义事件发生的话)在rect),或从运行时(如果它代表“应用程序”事件)。如果自定义事件是针对rect的,并且由于事件侦听器回调仅采用参数(事件),您应该在自定义事件中包含“目标”成员,以防侦听器想要知道哪个“rect”发送了事件。

local function tapListener( e )    -- local; only visible in this module
    local event = {
        name = "customEvent",
        myscustomvar = "this is my custom var",
        target = rect
    }
    rect:dispatchEvent( event )
end

注意如何在tapListener中使用rect,以便该函数需要访问rect。可能最好把tapListener放在Class.new()中:

function Class.new( )    -- constructor

    local rect = display.newRect( 0, 0, 50, 50 )

    local function tapListener( e )    -- local; only visible in this module
        local event = {
            name = "customEvent",
            myscustomvar = "this is my custom var",
            target = rect
        }
        rect:dispatchEvent( event )
    end

    rect:addEventListener( "tap", tapListener )

    ...
end

如果你不喜欢在构造函数中创建函数,还有其他方法,它们各有不同的优缺点。我个人喜欢把事情放在一起所以我赞成以上。您还可以将各种处理程序(如tapListener)移动到“侦听器工厂”功能,如下所示:

function bindCustomEventDispatcher(rect)
    local function tapListener(e) 
        local event = { ... } -- create custom event
        rect:dispatchEvent( event )
    end
    local function touchListener(e) 
        local event = { ... } -- create custom event
        rect:dispatchEvent( event )
    end
    local function zapListener(e) 
        local event = { ... } -- create custom event
        rect:dispatchEvent( event )
    end
    rect:addEventListener( "tap", tapListener )
    rect:addEventListener( "touch", touchListener )
    rect:addEventListener( "zap", zapListener )
end

我没有建议使用模块全局变量,因为它不能轻易地扩展到多个对象(rect实例),您必须使用数组。但如果这不是一个问题,那么你的方法是完全有效的。