CoronaSDK之交互系统和事件检测

事件(Event)是Corona应用程序的基础。他们用来触发不同事件对应的响应,例如触摸屏幕、检测一个特定的系统事件、定时器的完成、两个物理体的碰撞,等等。通常我们使用display object的对象方法addEventListener来添加处理函数,以关联需要监听的事件。

1 Runtime事件(似乎也可以叫做全局事件)

Runtime事件被分配给全局的Runtime监听器。这些事件并不直接和任何具体的对象相关;当然他们广播给所有感兴趣的监听器。Runtime event包括下列这些:

  • enterFrame:发生在每秒帧数间隔之间的事件(corona渲染一般每秒30或60帧)
  • system:某种由系统状况引发的事件,例如设备挂起应用或退出应用
  • orientation:当改变设备的方向,横向到竖向或者反之,而发生的事件

下面的代码展示了一个应用如何响应system事件:

local function onSystemEvent( event )

    local eventType = event.type

    if ( eventType == "applicationStart" ) then
        --occurs when the application is launched and all code in "main.lua" is executed
    elseif ( eventType == "applicationExit" ) then
        --occurs when the user or OS task manager quits the application
    elseif ( eventType == "applicationSuspend" ) then
        --perform all necessary actions for when the device suspends the application, i.e. during a phone call
    elseif ( eventType == "applicationResume" ) then
        --perform all necessary actions for when the app resumes from a suspended state
    elseif ( eventType == "applicationOpen" ) then
        --occurs when the application is asked to open a URL resource (Android and iOS only)
    end
end

Runtime:addEventListener( "system", onSystemEvent )

2 本地事件(local event)

本地事件被发送给一个单独的Listener,而不是广播给全局的运行时环境。一般本地事件包括下列事件:

hit:当用户触摸设备屏幕时发生的事件

collision:物理对象碰撞时发生的事件

timer:在运行timer完成时发生的事件

audio:当一个音频播放完成时分发的事件

3 function listener 和 table listener

Listener可以是一个function,也可以是一个table。

当你一个function Listener被调用,它会接受一个table参数,作为event。

local myListener = function( event )
    print( "Listener called with event of type: "..event.name )
end

Runtime:addEventListener( "touch", myListener )
Runtime:addEventListener( "enterFrame", myListener )

有时一个function Listener并不方便,因为当Listener被调用时一些变量并不在作用域里。在这种情况里,table Listener应该被使用。table Listener必须有一个有对应事件名的实例方法:

--assume myClass and myClass:new() already exist

function myClass:enterFrame( event )
    print( "enterFrame called at time: "..event.time )
end

function myClass:touch( event )
    print( "touch occurred at: "..event.x..","..event.y )
end

local myObject = myClass:new() 

Runtime:addEventListener( "touch", myObject )
Runtime:addEventListener( "enterFrame", myObject )

注意:

这里是对象方法,用的是“:”,而不是“.”。所以实际上函数内部是可以访问self引用的。这里的self就是myObject的引用。

4 理解hit事件

当用户触摸屏幕时,一个hit事件会生成并分发给显示层次中的显示对象(display object)。只有那些在屏幕上位置和触摸点位置发生交集的对象会收到事件。hit事件会以一个特定的顺序穿过这些对象。默认情况下,第一个收到事件的对象是发生交集的对象中最上层的显示对象,往下一个发生交集的显示对象会第二个收到事件,如此类推。

hit事件会一直传递下去,除非它被处理掉。这意味着如果你有多个层叠在一起的对象,并且一个hit事件监听器被应用到所有这些对象,hit事件将会穿过着所有的对象。然而,你可以停止传递给下一个低层对象,这就需要你告诉corona这个event已经被处理了。简单的方法就是在事件处理函数直接返回一个true--这将会停止传递周期,并且阻止任何底下对象响应这个hit事件。

local function myTouchListener( event )

    if ( event.phase == "began" ) then
        --code executed when the button is touched
        print( "object touched = "..tostring(event.target) )  --‘event.target‘ is the touched object
    end
    return true  --prevents touch propagation to underlying objects
end

local myButton = display.newRect( 100, 100, 200, 50 )
myButton:addEventListener( "touch", myTouchListener )

注意:如果hit事件遍历了整个显示层次中所有的显示对象,仍然没有被处理,它将会像全局事件一样广播给Runtime Listener。换言之,runtime listener还有机会对未命中任何对象的触摸事件做出反应。

4.1 设置焦点

你可以直接发送任何hit事件给一个指定的display object,来为这个对象设置焦点。比如一个典型的button,如果用户触摸这个按钮--还没有抬起手-又滑出了按钮,这个按钮一般不应该激发一个行为。同理,如果手指滑出按钮并接触到另一个交互对象,你可能不想激活那个对象,因为触摸是从按钮开始的,而不是交互对象。

解决这个问题的简单方法就如下,进入按钮时设置焦点,结束和取消时再取消焦点。这样滑出到其他对象时,其他对象都收不到事件:

local function myTouchListener( event )

    if ( event.phase == "began" ) then
        display.getCurrentStage():setFocus( event.target )  --‘event.target‘ is the touched object

    elseif ( event.phase == "ended" or event.phase == "cancelled" ) then
        display.getCurrentStage():setFocus( nil )  --setting focus to ‘nil‘ removes the focus

    end
    return true
end

local myButton = display.newRect( 100, 100, 200, 50 )
myButton:addEventListener( "touch", myTouchListener )

4.2 hit event具体分为

  • Tap
  • Touch
  • Multitouch

5 event 参数

上面举出的每个例子,事件都会被分发给事件监听函数。一个event参数始终会被传递给监听函数。

local function myTouchListener( event )

    print( "Touch X location"..event.x )
    print( "Touch Y location"..event.y )
end

local myButton = display.newRect( 100, 100, 200, 50 )
myButton:addEventListener( "touch", myTouchListener )

注意:传递给myTouchListener函数的event参数中包含手指接触屏幕位置的x和y坐标。event参数关联的属性和event类型是一一关联的。什么事件 对应哪些属性。

6 注册EventListener

我们一般用对象方法addEventListener()来注册事件。只要传入事件名称字符串,以及对应处理这个事件的处理函数即可。

--standard touch listener on an object
myButton:addEventListener( "touch", myTouchListener )

--Runtime ‘system‘ event listener
Runtime:addEventListener( "system", onSystemEvent )

重要提示:

如上所示,两种类型的事件监听器都可以通过addEventListener对象方法来创建:监听器附着到显示对象,或者监听器附着到全局Rumtime。

当你创建一个显示对象或添加一个本地的touch事件监听器 给它,你需要通过引用函数来指定一个代码块给事件。这些代码处于他们自己内存的代码段当中,并且当显示对象被删除后依然存在。不过当显示对象被删除后,就没办法检测到新的事件,因为本地事件监听器(注意:是监听器,不是代码)已经被有效的删除,并不需要你显式地删除监听器。

另一方面,Runtime事件监听器需要在你用完之后手动删除。此外,他们将继续运行,因为全局Runtime事件是全局的。不仅仅会导致内存泄漏,而且如果函数继续存在于Runtime中,并引用了不再存在的对象,程序也会崩溃。

7 删除Event Listener

大多数监听器(Listener),除了“enterFrame”之类的Runtime监听器,在显示对象被删除(obj:removeSelf或display.remove(obj))时将会被自动删除。但是,你也可以不删除对象,而只手动删除事件监听器。

删除(摘除)一个事件监听器,需要依靠内建的removeEventListener对象方法。

这个函数调用方式和addEventListener差不多。比如,你想让一个按钮停止监听touch事件,就可以摘除其监听器,如下:

myButton:removeEventListener( "touch", myTouchListener )

删除关联的事件监听器,需要提供事件名和函数名,因为有可能一个对象连接了同一类对象的多个监听器。例如,你可以有两个或更多监听函数关联到myButton的touch事件。然而当调用removeEventListener()时,你需要指定你想要停止监听的事件的类型,以及之前关联到这个事件上的函数。

时间: 2024-11-05 18:50:16

CoronaSDK之交互系统和事件检测的相关文章

基于meanshift的手势跟踪与电脑鼠标控制(手势交互系统)

转自网络:http://blog.csdn.net/zouxy09/article/details/17913745 基于meanshift的手势跟踪与电脑鼠标控制(手势交互系统) [email protected] http://blog.csdn.net/zouxy09 一年多前开始接触计算机视觉这个领域的时候,年幼无知,倍感吃力.当年惶恐,从而盲从.挣扎了不少时日,感觉自己好像还是处于领域的门外汉一样,在理论与实践的鸿沟中无法挣脱,心里空落落的.在这种挥之不去的烦忧中,某个时候豁然开朗,觉

从操作系统内核看Java非阻塞IO事件检测

非阻塞服务器模型最重要的一个特点是,在调用读取或写入接口后立即返回,而不会进入阻塞状态.在探讨单线程非阻塞IO模型前必须要先了解非阻塞情况下Socket事件的检测机制,因为对于非阻塞模式最重要的事情是检测哪些连接有感兴趣的事件发生,一般会有如下三种检测方式. 应用程序遍历socket检测 如图所示,当多个客户端向服务器请求时,服务器端会保存一个socket连接列表,应用层线程对socket列表进行轮询尝试读取或写入.对于读取操作,如果成功读取到若干数据则对读取到的数据进行处理,读取失败则下个循环

js html 交互监听事件学习

事件处理程序(handler): HTML事件处理程序: <input type="button" value="Click Here" onclick="showMessage();" /> <script type="text/javascript"> function showMessage() { alert('Clicked!'); } JavaScript指定事件处理程序: <inpu

HTML5 Canvas ( 事件交互, 点击事件为例 ) isPointInPath

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>canvas</title> <script type="text/javascript" src="../js/jQuery.js"></script> <style type="text/css">

μCOS-II系统之事件(event)的使用规则及Semaphore实例

*************************************************************************************************************************** 作者:EasyWave                                                时间:2014.05.31 类别:μC/OS-II-操作系统                                  声明:

μCOS-II系统之事件(event)的使用规则及Semaphore的互斥量用法

*************************************************************************************************************************** 作者:EasyWave                                                时间:2014.05.31 类别:μC/OS-II-操作系统                                  声明:

μCOS-II系统之事件(event)的使用规则及MUTEX实例

*************************************************************************************************************************** 作者:EasyWave                                                时间:2014.05.31 类别:μC/OS-II-操作系统                                  声明:

HTML5 Canvas ( 事件交互, 点击事件为例 ) isPointInPath(转)

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>canvas</title> <script type="text/javascript" src="../js/jQuery.js"></script> <style type="text/css">

如何设计一套通用消息交互系统

1.如何设计一套通用消息交互系统?(基于小程序与企业微信用户之间)  (1)在线聊天系统是否设计通用? 在线聊天系统,终端隔离,即发送端接受端使用唯一id,用于标识两个人员之间的独立,交互直接根据id直接进行交互,即可以根据令牌进行交互.消息系统并不关心终端用户是什么人,只关注两人之间的聊天. 用意: 聊天系统,不仅可以使用于一个xxxx场景,并且可以用于其他场景,利于电商版本当中商家与用户直接的聊天,等等. (2)消息扩展? 消息平台支持消息扩展,即通过第三方工具来建立未读消息提醒功能,目前系