懒动行不行 发表于 2023-7-10 11:13:37

【搬运Wowpedia】事件Events(四)

本帖最后由 懒动行不行 于 2023-7-10 11:14 AM 编辑

Handling events
事件是魔兽世界客户端发送给UI代码(框架派生的OnEvent脚本处理程序)的消息,主要是对游戏世界中发生的事情的反应。为了处理事件,插件需要创建一个事件处理程序,并为它希望接收的事件注册它。
目录

[*]1 设置事件处理器
[*]2 例子

[*]2.1 Hello World
[*]2.2 XML相关
[*]2.3 Lua相关
[*]2.4 可变参数表达式
[*]3 备注
[*]4 相关API


设置事件处理器
事件是被发送到框架派生的组件;如果插件尚未拥有可用于处理事件的框架,则需要创建一个框架。可以在Lua中使用CreateFrame函数创建框架;或用XML构造(使用<Frame>标签)
一旦创建了一个框架,其OnEvent处理程序就必须设置为代表插件处理事件的函数。OnEvent脚本处理程序可以使用Lua框架:SetScript()函数设置;或者用XML构造(使用<Scripts><OnEvent>函数主体</OnEvent></Scripts>)。

OnEvent 处理器函数接收至少2个参数:

[*]self, 对脚本处理程序所属框架的引用
[*]event,正在激发的事件的名称
[*]其他的事件参数都可以放置在可变参数表达式中 (...). 您可以从其中提取变量,只需将其分配给局部变量即可:例如从localarg1、arg2、arg3= ...;
插件的OnEvent脚本处理程序函数应该处理该事件,或者调用另一个插件函数来处理该事件。
为了接收事件通知,需要为插件需要处理的事件注册事件处理程序框架;使用frame:RegisterEvent(“eventName”)来实现这一点。RegisterEvent函数可以在框架创建后的任何时间调用;当使用XML时,OnLoad脚本处理程序是注册所需事件的方便位置。
如果您不再希望接收特定事件的事件通知,请使用frame:UnregisterEvent()函数。如果您希望禁用当前传递到框架的所有事件通知,请使用frame:UnregisterAllEvents()。


示例
Hello World

下面的两个实现方法在功能上是相同的:当角色进入世界时,它们将“Hello World!Hello PLAYER_ENTERING_World”打印到默认聊天框中。请注意,事件变量在XML OnEvent处理程序中是隐式的:它由OnEvent闭包签名提供。

使用XML
<Ui>
<Frame name="FooAddonFrame">
<Scripts>
   <OnLoad> self:RegisterEvent("PLAYER_ENTERING_WORLD"); </OnLoad>
   <OnEvent> print("Hello World! Hello " .. event); </OnEvent>
</Scripts>
</Frame>
</Ui>
使用 Lua
local frame = CreateFrame("FRAME", "FooAddonFrame");
frame:RegisterEvent("PLAYER_ENTERING_WORLD");
local function eventHandler(self, event, ...)
print("Hello World! Hello " .. event);
end
frame:SetScript("OnEvent", eventHandler);
XML-相关
您可以将已声明的Lua函数直接绑定到XML中的OnEvent处理程序,而不是通过在<OnEvent></OnEvent>标记中提供函数体来创建另一个函数。这样做可以节省内存:
function FooHandler_OnEvent(self, event, ...)
--这里插入事件处理器代码
end
FooAddOn.xml
<Ui>
<Script file="FooAddon.lua"/>
<Frame name="FooHandler">
<Scripts>
   <OnEvent function="FooHandler_OnEvent"/>
</Scripts>
</Frame>
</Ui>
Lua-相关
如果您的框架注册了大量事件,则可以减少If子句的所需数量,并通常通过以下操作简化设计:
local frame, events = CreateFrame("Frame"), {};
function events:PLAYER_ENTERING_WORLD(...)
-- handle PLAYER_ENTERING_WORLD here
end
function events:PLAYER_LEAVING_WORLD(...)
-- handle PLAYER_LEAVING_WORLD here
end
frame:SetScript("OnEvent", function(self, event, ...)
events(self, ...); -- call one of the functions above
end);
for k, v in pairs(events) do
frame:RegisterEvent(k); -- Register all events for which handlers have been defined
end
请注意,在上面的事件:XXX函数的情况下,通过使用函数表:functionName表示法隐式定义的变量self将指向处理事件的框架,而不是事件表。
可变参数表达式

可变参数表达式(…)可能包含事件提供的其他参数。包含在中的参数…可以通过简单地将它们分配给其他变量来读取,也可以使用select函数跳到列表中的特定参数。
请考虑处理COMBAT_LOG_EVENT的示例:
function eventHandler(self, event, ...)
if event == "COMBAT_LOG_EVENT" then
local timestamp, combatEvent, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags =
   ...; -- 这些参数为战斗事件的所有变量.
local eventPrefix, eventSuffix = combatEvent:match("^(.-)_?([^_]*)$");
if eventSuffix == "DAMAGE" then
   -- 某事造成了伤害.在 ... 中的后9个参数描述了造成了多少伤害.
   -- 为了提取这些变量, 我们可以使用 select 函数:
   local numArgumentsInVarArg = select("#", ...)
   local amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing =
    select(numArgumentsInVarArg - 8, ...);
   -- 用伤害的细节做些事情 ...
   if eventPrefix == "RANGE" or eventPrefix:match("^SPELL") then
    -- 这些前缀的前三个参数(出现在所有COMBAT_LOG_EVENT所有的11个参数之后)
    -- 描述法术或者技能造成伤害 . 用 select提取:
    local spellId, spellName, spellSchool = select(12, ...); -- Everything from 12th argument in ... onward
    -- 用技能的细节做些事情 ...
   end
end
end
end
备注
全局变量 this, event, 和 argX 在 Patch 4.0.1 版本中移除。替代地, 通过OnEvent脚本处理器使用这些参数。

相关API

[*]CreateFrame("widgetType"[, "name"[, parent[, "inherits"]]])
[*]frame:SetScript("handlerType", func)
[*]frame:HookScript("handlerType", func)
[*]frame:RegisterEvent("eventName") (and possibly frame:RegisterAllEvents() )
[*]frame:UnregisterEvent("eventName") (and possibly frame:UnregisterAllEvents() )
[*]frame:RegisterUnitEvent("eventName", "unit1"[, "unit2"])
[*]Events (API), a listing of events you may subscribe to.








页: [1]
查看完整版本: 【搬运Wowpedia】事件Events(四)