AsEvent事件小计

事件:

import mx.Events.PropertyChangeEvent;
import mx.Binding.utils.*;
import mx.Events.FlexEvent;

public var thiswatcher:ChangeWatcher;
public function initFunction():void
{
watchInit();
}
public function watchInit():void
{
 thiswatcher=ChangeWatcher.watch(textInput,"text" func);
// 告诉ChangeWatcher去监听那些变化
}
public function stopEvent():void
{
 if(thiswatch.isWatching())
 {
  thiswatcher.unwatch();//取消监听
 }
}
public function func():void
{
mylable.text=textInput.text;
}

 
//移除事件监听器 在mxml中定义的定义的事件必须使用removeEventListener();

来实现

import mx.controle.Alert;
[Bindable]
public var labeltext:Stirng="hello word";
public var count:Number=0;
public function  clickFunction(event:Event):void
{
var messag:String="hello "+event.target.label;
Alert.show(message);
}
public function addEvent():void
{
 if(myButtion.hasEventListener(MousEvetn.MOUS_OVER))
 {
  myButtion.removeEventListener

(MousEvetn.MOUS_OVER,changeLabel);
  count=0;
  labeltext="remove";
 }else
 {
  myButton.addEventListener

(MousEvetn.MOUS_OVER,changeLabel);

 }
}

public function changeLabel(event:MouseEvent):void
{
 count++;
}

 

//自定义事件

import flash.events.Event;
import mx.controls.Alert;
public function initFunction():void
{
 mybuttion.addEventListener("newEvent",respondEvent);
}
public function doEvent():void //click="doEvent"
{
 mybutton.dispatchEvent(new Event("newEvent"));
}
public function respondEvent(e:Event):void 
{
 Alert.show(e.type);
}

 

//自定义事件
 import flash.events.Event;
public class TestEvent extends Event
{
       public static const  TEST_EVENT:String="TEST_EVENT";//事件类型
   public var data:Object; //存储事件附加信息
   /**
    *自定义事件的构造器
    */
   public function TestEvent(type:String, bubbles:Boolean = false,

cancelable:Boolean = false)
  {
      super(type,bubbles,cancelable);
  }
} //end class

import flash.events.EventDispatcher;
import mx.controls.Alert;
public class TestEventDispacher extends EventDispatcher
{
 public function TestEventDispacher()
    {
     super();
//将onTestEvent成员函数作为该对象所派发的TestEvent事件的侦听//器以处理

传递给该事件
 this.addEventListener(TestEvent.TEST_EVENT,onTestEvent);
 }

 public function createAndDispatchTestEvent():void
    {
      //创建一个新事件对象,在被调度之前,事件对象的target属性为null
  var testEvent:TestEvent=new TestEvent(TestEvent.TEST_EVENT);
      //为事件添加附加信息data
  testEvent.data="this is a test event";
  //调度该事件,该方法执行后,事件的target属性被设置为
 // 执行该方法的TestEventDispacher对象。
      this.dispatchEvent(testEvent);
      Alert.show("当testEvent对象所有侦听器都执行完毕你才会看到我!");
    }
  //事件侦听器,用来对侦听到的事件进行处理。
private function onTestEvent(event:TestEvent):void
    {
   //在控制台中打印侦听器侦听到的TestEvent事件对象data属性中所存//储的

事件附加信息
 Alert.show(event.data.toString());
    }
}//end class
private function doOnButtonClick():void
{
 var ted:TestEventDispacher=new TestEventDispacher();
 ted.createAndDispatchTestEvent();  
}
在任何事件阶段都可以使用stopPropagation()和sotpimmediatePropagation();
这两个方法的本质上都是想相同的,区别在余是否允许同一个组件上
的其它时间按侦听器接受相应的事件换句话说,如果在事件上调用

evet.stopPropagation()
方法它会在给定的组件上的所有其它事件的侦听器完成对这个时间的响应之后停

止事件的传播
如果使用sotpimmediatePropagation();方法实践会在传播到其它任何事件侦听器

之前被终止,即使这些事件
侦听器侦听的是同一个组件

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 

layout="absolute"  creationComplete="initFunction()">
 <mx:Script>
  <![CDATA[
import mx.controls.Alert;
public function initFunction():void
{
 mybutton.addEventListener("click",respondToEvent,false,100);//

添加带有最高优先级的事件侦听器
 myHBox.addEventListener("click",parentEventResponse,false,0);
}
public function respondToEvent(e:Event):void 
{
 var msg:String="this is the first responder";
 Alert.show(msg,"first event listener");
 e.stopImmediatePropagation();
}
public function responedEventClick(e:Event):void
{
 Alert.show("this is the mxml click Event");
}

public function parentEventResponse(e:Event):void
{
 Alert.show("you shoud never see ths alert","parent Event 

Response");
}
  ]]>
 </mx:Script>
 <mx:HBox x="158" y="180" width="291" height="165" id="myHBox">
  <mx:Button label="Button" id="mybutton" 

click="responedEventClick(event)"/>
 </mx:HBox>
</mx:Application>

 

如果把e.stopPropagation()修改成e.stopImmediatePropagation();
结果看到的是一个警告e.stopImmediateP事件ropagation()方法会在第一个事件

侦听器执行完毕后
立即终止传播而e.stopPropagation();终止当前的事件传播
stopImmediatePropagation():void
防止对事件流中当前节点中和所有后续节点中的事件侦听器进行处理。防止对事

件流中当前节点中和所有后续节点中的事件侦听器进行处理。此方法会立即生效

,并且会影响当前节点中的事件侦听器。相比之下,在当前节点中的所有事件侦

听器都完成处理之前,stopPropagation() 方法不会生效。
stopPropagation():void
防止对事件流中当前节点的后续节点中的所有事件侦听器进行处理。防止对事件

流中当前节点的后续节点中的所有事件侦听器进行处理。 此方法不会影响当前节

点 (currentTarget) 中的任何事件侦听器。相比之下,

stopImmediatePropagation() 方法可以防止对当前节点中和后续节点中的事件侦

听器进行处理。 对此方法的其它调用没有任何效果。可以在事件流的任何阶段中

调用此方法。

如果使用 e.stopPropagation(),结果
 btn  click
hbox  click
否则如果没有使用的话,
btn  click
hbox  click
pan  click
stage  click
//主键添加元数据
<mx:Metadate>
 [Event(name="customButtonClick",true)]
</mx:Metadate>
this.dispatchEvent(new Event("customButtonClick"),true);

相关code:

 

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Metadata> 
        [Event(name="customButtonClick", type="flash.events.Event")] 
    </mx:Metadata> 
    
    <mx:Script>
     <![CDATA[
      
      public function doCustomEvent():void {
       
       this.dispatchEvent(new Event("customButtonClick",true));
      }
     ]]>
    </mx:Script>
    
    <mx:Button id="myButton" label="click me to dispatch custom event" click="doCustomEvent()"/>
</mx:VBox>

 

------------------------------------------------------------------------------------------------------

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:comp="components.*">
 
 <mx:Script>
  <![CDATA[
   
   import mx.controls.Alert;
   
   public function doAlert(e:Event):void {
    
    Alert.show("this is the alert thrown from the parent app in response to component custom event","component custom event");
   }
  ]]>
 </mx:Script>
 <comp:CustomEventMeta customButtonClick="doAlert(event)"/>
</mx:Application>

 

1.不是所有的事件都有三个阶段:Capture,Target,Bubbling。
事件只有在DisplayObject才上有Capturing和Bubbling阶段。

2.Target是派发该事件的对象。CurrentTarget是监听了该事件并正在处理该事

件的对象。

3.Capturing流程:StageàSystemManageràApplicationà…à派发该事件的父对象

4.Bubbling流程:派发该事件的父对象à…àApplicationàSystemManageràStage

5.在mxml标签中定义的事件监听器是无法用removeEventListener()去掉的,并

且无法设置useCapture和priority属性。

6.用removeEventListener()去掉未添加的事件器时是不会报错的,所有无需用

hasEventListener()判断,但添加时需要判断,否则可能会添加多次。

7.Priority越大的监听器,越先执行。

8.weakRef对于非内嵌函数没用。

9.一个对象可以给同一个事件多个监听器:

假如按添加顺序是eventListener1,eventListener2和eventListener3。

eventListener1没有调stopPropagation()和stopImmediatePropagation()方法。

假设eventListener2调了其中的stopPropatation(),则eventListener3还会继续

执行。但如果eventListener2调的是stopImmediatePropagation(),则

eventListener3不会继续执行。

10.removeEventListener()只能一次去掉一个监听器,为同一个事件添加了几个

监听器就需要调几次removeEventListener(),而且参数要相符。

11.hasEventListener()与willTrigger()的区别是:hasEventListener()只检查

它所属的对象,而willTrigge()检查整个事件流以查找由type参数指定的事件。

12.keyCode对应的是key在键盘上的键值,是一个数字;charCode对应的是该key

在当前字符集中的值,也是一个数字。因此就有下面的情况发生:1和!的keyCode

是一样的,但他们的charCode是不一样的。


事件只有在DisplayObject才上有Capturing和Bubbling阶段。

从根节点到叶节点的父对象

从叶节点的父对象到根节点

如果设为true,只有内嵌函数可能会被垃圾回收器处理。

指stopPropagation()和stopImmediatePropagation()

use_capture

包括检查所有的父对象。

keyCode和keyChar都是KeyBoardEvent的属性。

修改::#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 事件系统模块 - 包含事件类型定义和事件中心实�? """ import threading from enum import Enum from collections import defaultdict from typing import Callable, List, Tuple, Optional, Dict, Any import uuid from dataclasses import dataclass, field import logging import unittest logger = logging.getLogger(__name__) # 使用安全的导入方�? try: from core.event_types import EventType EVENT_TYPES_AVAILABLE = True except ImportError as import_error: # 提供回退实现 logger.warning(f"无法导入 EventType: {import_error}, 使用回退实现") EVENT_TYPES_AVAILABLE = False # 回退的事件类型枚�? class EventType(Enum): """增强的事件类型枚�?"" MODULE_RUN = "module_run" DATA_SUBMIT = "data_submit" COMMAND = "command" DATA_RESULT = "data_result" MODULE_ERROR = "module_error" MODULE_READY = "module_ready" MODULE_COMPLETE = "module_complete" ANALYSIS_RESULT = "analysis_result" COMBINATION_RESULT = "combination_result" FOLLOW_RESULT = "follow_result" TREND_ANALYSIS_RESULT = "trend_analysis_result" NUMBER_GENERATION_RESULT = "number_generation_result" UI_UPDATE = "ui_update" EXCLUDE_NUMBERS = "exclude_numbers" DATA_FREEZE = "data_freeze" ORGANIZE_DATA = "organize_data" NUMBER_UPDATE = "number_update" TEST_EVENT = "test_event" @dataclass class Event: event_id: str type: str source: str target: Optional[str] = None data: Dict[str, Any] = field(default_factory=dict) token: Optional[str] = None def __post_init__(self): # 如果 EventType 可用,验证事件类�? if EVENT_TYPES_AVAILABLE: valid_types = [e.value for e in EventType] if not isinstance(self.type, str) or self.type not in valid_types: raise ValueError(f"无效事件类型: {self.type}, 有效类型: {valid_types}") elif not isinstance(self.type, str): raise ValueError(f"事件类型必须是字符串: {type(self.type)}") def is_valid(self) -> bool: """验证事件基本完整�?"" if EVENT_TYPES_AVAILABLE: type_valid = self.type in [e.value for e in EventType] else: # 如果没有 EventType,只要类型是字符串就认为是有效的 type_valid = isinstance(self.type, str) return all([ bool(self.event_id), type_valid, isinstance(self.data, dict) ]) class EventCenter: """ 线程安全的事件中心实现(单例模式�? """ _instance = None _lock = threading.Lock() def __new__(cls): if cls._instance is None: with cls._lock: if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance def __init__(self): if hasattr(self, '_initialized'): return self._subscribers = defaultdict(list) self._lock = threading.Lock() self._initialized = True logger.info("事件中心初始化完�?) def subscribe( self, event_type: str, handler: Callable[[Event], None], token: Optional[str] = None ): """ 订阅指定类型的事�? :param event_type: 事件类型 :param handler: 回调函数 :param token: 可选的订阅令牌 """ # 如果 EventType 可用,验证事件类�? if EVENT_TYPES_AVAILABLE: valid_types = [e.value for e in EventType] if event_type not in valid_types: raise ValueError(f"无效事件类型: {event_type}, 有效类型: {valid_types}") with self._lock: self._subscribers[event_type].append((handler, token)) logger.debug(f"已订阅事�? {event_type}, token: {token}") def publish(self, event: Event): """ 发布一个事件到所有订阅�? :param event: Event 对象 """ if not event.is_valid(): raise ValueError("无效事件对象") handlers = self._subscribers.get(event.type, []) if not handlers: logger.debug(f"没有订阅者处理事�? {event.type}") return logger.debug(f"发布事件: {event.type}, 来源: {event.source}, 目标: {event.target}") for handler, token in handlers: try: # 检查token匹配 if token is None or event.token == token: handler(event) except Exception as exc: logger.error(f"事件处理失败 - 类型: {event.type}, 来源: {event.source}, 错误: {exc}") def unsubscribe( self, event_type: str, token: Optional[str] = None, handler: Optional[Callable] = None ): """ 取消订阅 :param event_type: 事件类型 :param token: 可选的订阅令牌 :param handler: 可选的回调函数 """ with self._lock: if event_type in self._subscribers: original_count = len(self._subscribers[event_type]) self._subscribers[event_type] = [ cb for cb in self._subscribers[event_type] if (token is None or cb[1] != token) and (handler is None or cb[0] != handler) ] removed_count = original_count - len(self._subscribers[event_type]) logger.debug(f"取消订阅事件: {event_type}, 移除 {removed_count} 个处理器") def get_subscriber_count(self, event_type: str) -> int: """获取指定事件类型的订阅者数�?"" return len(self._subscribers.get(event_type, [])) def clear_subscribers(self, event_type: Optional[str] = None): """清除订阅�?"" with self._lock: if event_type: if event_type in self._subscribers: removed_count = len(self._subscribers[event_type]) del self._subscribers[event_type] logger.debug(f"清除事件 {event_type} �?{removed_count} 个订阅�?) else: total_count = sum(len(handlers) for handlers in self._subscribers.values()) self._subscribers.clear() logger.debug(f"清除所�?{total_count} 个订阅�?) # 便捷函数 def create_event(event_type: str, source: str, target: Optional[str] = None, data: Optional[Dict[str, Any]] = None, token: Optional[str] = None) -> Event: """创建事件对象的便捷函�?"" return Event( event_id=str(uuid.uuid4()), type=event_type, source=source, target=target, data=data or {}, token=token ) # 全局事件中心实例 event_center = EventCenter() class TestEventSystem(unittest.TestCase): """事件系统单元测试""" def setUp(self): """测试前清理事件中�?"" event_center.clear_subscribers() def test_event_creation(self): """测试事件创建""" event = create_event("test_event", "test_source", data={"key": "value"}) self.assertTrue(event.is_valid()) self.assertEqual(event.type, "test_event") self.assertEqual(event.source, "test_source") self.assertEqual(event.data["key"], "value") def test_event_subscribe_publish(self): """测试事件订阅和发�?"" received_events = [] def test_handler(event_obj): received_events.append(event_obj) # 订阅事件 event_center.subscribe("test_event", test_handler) # 发布事件 test_event = create_event("test_event", "test_source", data={"message": "hello"}) event_center.publish(test_event) self.assertEqual(len(received_events), 1) self.assertEqual(received_events[0].data["message"], "hello") def test_token_matching(self): """测试token匹配""" received_with_token = [] received_without_token = [] def handler_with_token(event_obj): received_with_token.append(event_obj) def handler_without_token(event_obj): received_without_token.append(event_obj) # 订阅带token的事�? event_center.subscribe("test_event", handler_with_token, "secret_token") event_center.subscribe("test_event", handler_without_token) # 发布带token的事�? event_with_token = create_event("test_event", "source", token="secret_token") event_center.publish(event_with_token) # 发布不带token的事�? event_without_token = create_event("test_event", "source") event_center.publish(event_without_token) self.assertEqual(len(received_with_token), 1) self.assertEqual(len(received_without_token), 2) # 两个事件都会收到 def test_unsubscribe(self): """测试取消订阅""" received_events = [] def test_handler(event_obj): received_events.append(event_obj) # 订阅事件 event_center.subscribe("test_event", test_handler) # 发布事件 event_obj = create_event("test_event", "source") event_center.publish(event_obj) self.assertEqual(len(received_events), 1) # 取消订阅 event_center.unsubscribe("test_event", handler=test_handler) # 再次发布事件 event_center.publish(event_obj) self.assertEqual(len(received_events), 1) # 应该没有增加 def test_subscriber_count(self): """测试订阅者计�?"" def handler1(event_obj): """测试处理�?""" # 故意留空,用于测试计�? def handler2(event_obj): """测试处理�?""" # 故意留空,用于测试计�? event_center.subscribe("event1", handler1) event_center.subscribe("event1", handler2) event_center.subscribe("event2", handler1) self.assertEqual(event_center.get_subscriber_count("event1"), 2) self.assertEqual(event_center.get_subscriber_count("event2"), 1) self.assertEqual(event_center.get_subscriber_count("event3"), 0) # 主程序入�? def main(): """主函�?- 用于直接运行测试""" # 设置日志 logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') # 运行单元测试 unittest.main(argv=[''], verbosity=2, exit=False) # 演示功能 print("\n" + "=" * 50) print("事件系统演示") print("=" * 50) def demo_handler(event_obj): print(f"收到事件: {event_obj.type}, 数据: {event_obj.data.get('message', '无数�?)}") # 订阅演示事件 event_center.subscribe("demo_event", demo_handler) # 发布演示事件 demo_event = create_event("demo_event", "demo_source", data={"message": "Hello Event System!"}) event_center.publish(demo_event) print("演示完成") if __name__ == "__main__": # 如果直接运行此文件,执行主函�? main() __all__ = ['Event', 'EventCenter', 'EventType', 'event_center', 'create_event']
最新发布
09-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值