先抛开一切,我们来想一想,如果自己要写一个事件驱动引擎会怎么写?之前也说过,所谓的事情驱动就是你要监听一些事件,当某些事件发生的时候,要分配相对应的方法进行处理。完成这个过程的东西我们抽象出来之后就叫做事件驱动引擎了。那么,如果我们自己写的话,应该有这样几个功能:
- 1.事件的注册和取消,使用者可以根据自己的需求来设置引擎需要关心那些事件
- 2.事件对于的处理方法的挂钩。显然,一个事件可以由多个方法来处理,也可以一个方法处理多个事件。
- 3.不断监听事件的发生与否,如果发生就进行相应的处理,也就是调用设置好的函数。
有了上面的共识,我们就可以开始分析源代码了。在nvpy/event/eventEngine.py里面,我们可以看到源代码。
里面有三个类,分别是EventEngine,EventEngine2 和Event。其中,EventEngine和EventEngine2是一回事,只不过在定时器的使用过程中一个用了pyqt包里面的定时器Qtimer,一个用了python的线程自己实现的。那么这里我们还是讨论EventEngine,毕竟别的地方没什么区别。
class EventEngine(object):
"""
事件驱动引擎
事件驱动引擎中所有的变量都设置为了私有,这是为了防止不小心
从外部修改了这些变量的值或状态,导致bug。
变量说明
__queue:私有变量,事件队列
__active:私有变量,事件引擎开关
__thread:私有变量,事件处理线程
__timer:私有变量,计时器
__handlers:私有变量,事件处理函数字典
方法说明
__run: 私有方法,事件处理线程连续运行用
__process: 私有方法,处理事件,调用注册在引擎中的监听函数
__onTimer:私有方法,计时器固定事件间隔触发后,向事件队列中存入计时器事件
start: 公共方法,启动引擎
stop:公共方法,停止引擎
register:公共方法,向引擎中注册监听函数
unregister:公共方法,向引擎中注销监听函数
put:公共方法,向事件队列中存入新的事件
事件监听函数必须定义为输入参数仅为一个event对象,即:
函数
def func(event)
...
对象方法
def method(self, event)
...
"""
#----------------------------------------------------------------------
def __init__(self):
"""初始化事件引擎"""
# 事件队列
self.__queue = Queue()
# 事件引擎开关
self.__active = False
# 事件处理线程
self.__thread = Thread(target=self.__run)
# 计时器,用于触发计时器事件
self.__timer = QTimer()
self.__timer.timeout.connect(self.__onTimer)
# 这里的__handlers是一个字典,用来保存对应的事件调用关系
# 其中每个键对应的值是一个列表,列表中保存了对该事件进行监听的函数功能
self.__handlers = defaultdict(list)
# __generalHandlers是一个列表,用来保存通用回调函数(所有事件均调用)
self.__generalHandlers = []
#----------------------------------------------------------------------
def __run(self):
"""引擎运行"""
while self.__active == True:
try:
event = self.__queue.get(block=True, timeout=1) # 获取事件的阻塞时间设为1秒
self.__process(event)
except Empty:
pass
#----------------------------------------------------------------------
def __process(self, event):
"""处理事件"&#