打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
python实现事件监听

python实现事件监听

每一个ui框架都需要一个事件监听体系,下面代码演示怎么用python实现事件监听系统,我们定义一个Event类,一般需要确定定义事件的类型,和event传递的数据:如在js中事件类型有click,mouseover,keypress... 事件的数据就是触发此事件的时候产生的数据如:产生事件的位置,...

class Event( object ):    """    Generic event to use with EventDispatcher.    用于事件分发    """    def __init__(self, event_type, data=None):        """        The constructor accepts an event type as string and a custom data        定义event的类型和数据        """        self._type = event_type        self._data = data    @property    def type(self):        """        Returns the event type        返回event类型        """        return self._type    @property    def data(self):        """        Returns the data associated to the event        返回event传递的数据        """        return self._data

这个就是一个简单的event类,如果你写过ui程序,或者js程序的对event对象应该都不陌生,如jquery中的click方法中传递给bind的函数的参数就是一个event实例pyside或者pyqt中也是这样

现在我们写事件分发类,如下:

class EventDispatcher( object ):    """    Generic event dispatcher which listen and dispatch events    event分发类 监听和分发event事件    """    def __init__(self):        """        初始化类        """        self._events = dict()    def __del__(self):        """        清空所有event        """        self._events = None    def has_listener(self, event_type, listener):        """        Return true if listener is register to event_type        返回注册到event_type的listener        """        # Check for event type and for the listener        if event_type in self._events.keys():            return listener in self._events[ event_type ]        else:            return False    def dispatch_event(self, event):        """        Dispatch an instance of Event class        """        # 分发event到所有关联的listener        if event.type in self._events.keys():            listeners = self._events[ event.type ]            for listener in listeners:                listener( event )    def add_event_listener(self, event_type, listener):        """        Add an event listener for an event type        给某种事件类型添加listener        """        # Add listener to the event type        if not self.has_listener( event_type, listener ):            listeners = self._events.get( event_type, [] )            listeners.append( listener )            self._events[ event_type ] = listeners    def remove_event_listener(self, event_type, listener):        """        移出某种事件类型的所以listener        """        # Remove the listener from the event type        if self.has_listener( event_type, listener ):            listeners = self._events[ event_type ]            if len( listeners ) == 1:                # Only this listener remains so remove the key                del self._events[ event_type ]            else:                # Update listeners chain                listeners.remove( listener )                self._events[ event_type ] = listeners

The constructor of the EventDispatcher class simply create an empty “protected” dictionary of event->listeners and set to None it when del() method is called. Because del() method is called when the class is about to be destroyed we are sure no reference to listeners are left in memory.The exampleIn this example we create a simple event, MyEvent, and two classes: a class who send events. WhoAsk, and a class who listen for events and send a response back to the sender through another event, WhoRespond.下面我们自定义一个event类,并且写两个类一个触发事件一个应答事件

class MyEvent( Event ):    """    When subclassing Event class the only thing you must do is to define    a list of class level constants which defines the event types and the    string associated to them    """    ASK     = "askMyEvent"    RESPOND = "respondMyEvent"

The method is very simple, only two events are implemented, ASK and RESPOND.

class WhoAsk( object ):    """    First class which ask who is listening to it    """    def __init__(self, event_dispatcher):        # Save a reference to the event dispatch        self.event_dispatcher = event_dispatcher        # Listen for the RESPOND event type        self.event_dispatcher.add_event_listener(            MyEvent.RESPOND, self.on_answer_event        )    def ask(self):        """        Dispatch the ask event        """        print ">>> I'm instance {0}. Who are listening to me ?".format( self )        self.event_dispatcher.dispatch_event(            MyEvent( MyEvent.ASK, self )        )    def on_answer_event(self, event):        """        Event handler for the RESPOND event type        """        print "<<< Thank you instance {0}".format( event.data )

The WhoAsk class adds an event listener for the MyEvent.RESPOND event and implement and ask() method which dispatch and MyEvent.ASK.

class WhoRespond( object ):    """    Second class who respond to ASK events    """    def __init__(self, event_dispatcher):        # Save event dispatcher reference        self.event_dispatcher = event_dispatcher        # Listen for ASK event type        self.event_dispatcher.add_event_listener(            MyEvent.ASK, self.on_ask_event        )    def on_ask_event(self, event):        """        Event handler for ASK event type        """        self.event_dispatcher.dispatch_event(            MyEvent ( MyEvent.RESPOND, self )        )

WhoResponde class is similar to WhoAsk class except it has only the listener for the MyEvent.ASK event.Both WhoAsk and WhoRepsond classes accepts the instance of EventDispatcher class as a parameter for their constructors.Finally we test our example:

Create and instance of event dispatcher

dispatcher = EventDispatcher()

Create an instance of WhoAsk class and two instance of WhoRespond class

who_ask = WhoAsk( dispatcher )who_responde1 = WhoRespond( dispatcher )who_responde2 = WhoRespond( dispatcher )# WhoAsk ask who_ask.ask()

We create an instance of EventDispatcher class, and instance of WhoAsk class and two instance of WhoRespond class, then we call the ask() method of WhoAsk class.

$ python eventdispatcher.py>>> I'm instance <__main__.WhoAsk object at 0x100491ad0>. Who are listening to me ?<<< Thank you instance <__main__.WhoRespond object at 0x100491b10><<< Thank you instance <__main__.WhoRespond object at 0x100491b50>

As you can see we get two MyEvent.RESPOND events for the MyEvent.ASK event because we have two classes which listen to it.Conclusion

Develop a simple event dispatcher mini-framework is really straight forward, and is some situations is more simple to use a custom event dispatcher system than try to adapt a third-party one.

If you want to learn more about event driven system, take a look at PubSub, Qt Signals and Slots and wxPython. The documentation for Qt Signals and Slots reports examples in C++ but if you use

PyQt or PySide the classes, methods and logic is the same.Here you can download the source code for the Event and EventDisatcher classes with also the example code.

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
python – 基于值而不是类型的Singledispatch
Chapter 6: Object
DRF终极封装ViewSet和Router附教程PDF源码
[python-win32] DispatchWithEvents design ques...
Python 流媒体播放器(基于VLC)
disruptor - 并发编程框架
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服