diff --git a/vn.event/eventEngine.py b/vn.event/eventEngine.py new file mode 100644 index 00000000..7d4766b9 --- /dev/null +++ b/vn.event/eventEngine.py @@ -0,0 +1,178 @@ +# encoding: UTF-8 + +# 系统模块 +from Queue import Queue, Empty +from threading import Thread + +# 第三方模块 +from PyQt4.QtCore import QTimer + +# 自己开发的模块 +from eventType import * + + +######################################################################## +class EventEngine: + """ + 事件驱动引擎 + + 方法说明 + __run: 私有方法,事件处理线程连续运行用 + __process: 私有方法,处理事件,调用注册在引擎中的监听函数 + __onTimer:私有方法,计时器固定事件间隔触发后,向事件队列中存入计时器事件 + start: 公共方法,启动引擎 + stop:公共方法,停止引擎 + register:公共方法,向引擎中注册监听函数 + unregister:公共方法,向引擎中注销监听函数 + + 事件监听函数必须定义为输入参数仅为一个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 = {} + + #---------------------------------------------------------------------- + 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): + """处理事件""" + # 检查是否存在对该事件进行监听的处理函数 + if event.type_ in self.handlers: + # 若存在,则按顺序将事件传递给处理函数执行 + for handler in self.handlers[event.type_]: + handler(event) + + #---------------------------------------------------------------------- + def __onTimer(self): + """向事件队列中存入计时器事件""" + # 创建计时器事件 + event = Event(type_=EVENT_TIMER) + + # 向队列中存入计时器事件 + self.queue.put(event) + + #---------------------------------------------------------------------- + def start(self): + """引擎启动""" + # 将引擎设为启动 + self.active = True + + # 启动事件处理线程 + self.thread.start() + + # 启动计时器,计时器事件间隔默认设定为1秒 + self.timer.start(1000) + + #---------------------------------------------------------------------- + def stop(self): + """停止引擎""" + # 将引擎设为停止 + self.active = False + + # 停止计时器 + self.timer.stop() + + # 等待事件处理线程退出 + self.thread.join() + + #---------------------------------------------------------------------- + def register(self, type_, handler): + """注册事件处理函数监听""" + # 尝试获取该事件类型对应的处理函数列表,若无则创建 + try: + handlerList = self.handlers[type_] + except KeyError: + handlerList = [] + self.handlers[type_] = handlerList + + # 若要注册的处理器不在该事件的处理器列表中,则注册该事件 + if handler not in handlerList: + handlerList.append(handler) + + #---------------------------------------------------------------------- + def unregister(self, type_, handler): + """注销事件处理函数监听""" + # 尝试获取该事件类型对应的处理函数列表,若无则忽略该次注销请求 + try: + handlerList = self.handlers[type_] + + # 如果该函数存在于列表中,则移除 + if handler in handlerList: + handlerList.remove(handler) + + # 如果函数列表为空,则从引擎中移除该事件类型 + if not handlerList: + del self.handlers[type_] + except KeyError: + pass + + + + +######################################################################## +class Event: + """事件对象""" + + #---------------------------------------------------------------------- + def __init__(self, type_=None): + """Constructor""" + self.type_ = type_ # 事件类型 + self.dict_ = {} # 字典用于保存具体的事件数据 + + +#---------------------------------------------------------------------- +def test(): + """测试函数""" + import sys + from datetime import datetime + from PyQt4.QtCore import QCoreApplication + + def simpletest(event): + print str(datetime.now()) + + app = QCoreApplication(sys.argv) + + ee = EventEngine() + ee.register(EVENT_TIMER, simpletest) + ee.start() + + app.exec_() + + +# 直接运行脚本可以进行测试 +if __name__ == '__main__': + test() \ No newline at end of file diff --git a/vn.event/eventType.py b/vn.event/eventType.py new file mode 100644 index 00000000..8ce348e1 --- /dev/null +++ b/vn.event/eventType.py @@ -0,0 +1,45 @@ +# encoding: UTF-8 + +''' +本文件仅用于存放对于事件类型常量的定义。 + +由于python中不存在真正的常量概念,因此选择使用全大写的变量名来代替常量。 +这里设计的命名规则以EVENT_前缀开头。 + +常量的内容通常选择一个能够代表真实意义的字符串(便于理解)。 + +建议将所有的常量定义放在该文件中,便于检查是否存在重复的现象。 +''' + + +EVENT_TIMER = 'eTimer' # 计时器事件,每隔1秒发送一次 + + + +#---------------------------------------------------------------------- +def test(): + """检查是否存在内容重复的常量定义""" + check_dict = {} + + global_dict = globals() + + for key, value in global_dict.items(): + if '__' not in key: # 不检查python内置对象 + if value in check_dict: + check_dict[value].append(key) + else: + check_dict[value] = [key] + + for key, value in check_dict.items(): + if len(value)>1: + print u'存在重复的常量定义:' + str(key) + for name in value: + print name + print '' + + print u'测试完毕' + + +# 直接运行脚本可以进行测试 +if __name__ == '__main__': + test() \ No newline at end of file