Event.INIT Event.COMPLETE 区别

本文介绍了在Flash中使用Loader类加载和显示资源的三种方法,并详细解释了如何通过Loader实例访问加载的内容。此外,还探讨了如何正确为Loader添加事件监听器以处理加载过程中的不同事件类型,如Event.INIT和Event.COMPLETE。

 

访问Loader内容的方法小结和为Loader添加侦听

 

访问用Loader加载进来的显示资源的时候,通常有3种办法,比如,myLoader是Loader类型的实例,要访问其加载的内容,可以这样:

1,myLoader.content;//直接访问实例的content

2,myLoader.getChildAt(0);//被加载的资源是myLoader的唯一孩子

3,e.target.content;//在侦听函数里面通过事件的目标对象访问

如果要为Loader添加侦听,必须通过Loader的实例变量contentLoaderInfo注册,contentLoaderInfo变量提供了对它装载资源的LoaderInfo对象的一个引用。而不能直接在Loader的实例上添加侦听!

以下代码简单展示了访问装载资源对象的方法和添加侦听的方法,有一个小疑惑啊,事件类型Event.COMPLETE和Event.INIT有什么区别,只知道前者是在加载结束之后触发,后者是在加载初始化后触发。牢记一点Event.COMPLETE永远发生的比Event.INIT晚 ,所以是不是在更多的情况下考虑使用Event.COMPLETE?

参考书对Event.INIT的解释如下

1,对位图而言,实例化发生于当外部文件已经完全装载的时候。在那个时期,被装载的像素数据自动地被放置在一个BitmapData对象中,然后它被关联于一个新的Bitmap对象,改Bitmap对象表示被装载的图像。(是不是对位图而言Event.INIT跟Event.COMPLETE是一样的?)

2,对于swf文件,实例化发生于当在帧1的所有资源和类(包括.swf的主类)已经被接收到的时候。在那个时期,ActionScript创建.swf主类的一个实例,并执行它的构造器。该主类实例表示被装载的.swf文件。

注意,千万不要在初始化完成之前(Event.INIT触发之前)或者加载完成之前(Event.COMPLETE触发之前)试图访问被加载的资源。此时会报错,如果用myLoader.content访问,content此时为空,如果用myLoader.getChildAt(0)访问则报错,错误为:RangeError:Error #2006

当被装载的资源对象添加到一个新的DisplayObjectContainer中,被装载的资源自动从它原来的父亲容器Loader对象中移除!

 

package{
 import flash.display.*;
 import flash.events.Event;
 import flash.net.URLRequest;
 public class LoadJPG extends Sprite{
  private var myLoader:Loader;
  public function LoadJPG(){
   myLoader=new Loader();
   myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeListener);
   myLoader.contentLoaderInfo.addEventListener(Event.INIT,initListener);
   myLoader.load(new URLRequest("fengjing.jpg"));
  }//end of constructor function LoadJPG
  private function completeListener(e:Event):void{
   trace("This is from Event.COMPLETE listener");
   trace(myLoader.content.width);
   trace(myLoader.getChildAt(0).height);
   trace(e.target.content.rotation);
   trace("添加到显示列表前 : ",myLoader.numChildren);//1
   addChild(myLoader.content);
   trace("添加到显示列表后 : ",myLoader.numChildren);//0
  }//end of function completeListener
  private function initListener(e:Event):void{
   trace("This is from Event.INIT listener");
   trace(myLoader.content.width);
   trace(myLoader.getChildAt(0).height);
   trace(e.target.content.rotation);          
  }//end of function initListener
 }//end of class LoadJPG 
}//end of package
 

 

http://dailythink.blog.sohu.com/129101250.html  said, thank you !

 

修改::未解析的引用 'logger',,已重新声明上文定义的无用法的 '_setup_event_subscriptions',,从外部作用域隐藏名称 'event_center',方法 'update_module_display' 可能为 'static',,代码# ---------- 主界面 - 修复类型错误和添加所有模块支持 ---------- class MainInterface: def __init__(self, root_window, event_center): self.root = root_window self.event_center = event_center self.root.title(GlobalConfig.VERSION) self.root.geometry("1400x800") self.root.protocol("WM_DELETE_WINDOW", self.on_close) # 初始化实例变量 self.period_var = None self.dynamic_content = None self.run_button = None self.clear_button = None self.save_button = None self.refresh_button = None self.core_vars = {} self.pool_vars = {} self.dynamic_vars = {} self.status_var = None self.status_bar = None self.current_module = None self._current_token = None # 修复实例特性定义 self.token_var = None self.main_frame = None self.micro_server = None # 初始化组件 self.comm_manager = CommunicationManager() self.number_pool = NumberPool() self.modules = {} for module_id in GlobalConfig.MODULE_IDS.keys(): self.modules[module_id] = ModuleFactory.create_module(module_id) self.token_manager = TokenManager() self._current_token = self.token_manager.get_token() self.token_var = tk.StringVar(value=self._current_token) self.main_frame = tk.Frame(root_window) self.main_frame.pack(fill='both', expand=True, padx=10, pady=10) self.create_left_panel() self.create_center_panel() self.create_right_panel() self.status_var = tk.StringVar(value="就绪") self.status_bar = tk.Label( root_window, textvariable=self.status_var, bd=1, relief='raised', anchor='w' ) self.status_bar.pack(side='bottom', fill='x') self.token_manager.register_token_callback(self._on_token_update) self._setup_event_subscriptions() self.micro_server = MicroServer(65432) self.micro_server.start() # 启动TCP服务器 self.tcp_server = self.TCPServer() self.tcp_server.start() def _setup_event_subscriptions(self): """设置事件订阅""" # 订阅模块结果事件 for module_id in ['module1', 'module2', 'module3', 'module4', 'module5']: self.event_center.subscribe(f"{module_id}_result", handler=self.handle_module_result) def handle_module_result(self, event: Event): """处理模块返回的结果""" token = event.data.get('token') result = event.data.get('result') labels = event.data.get('labels', {}) # 根据token更新对应的UI显示 self.update_module_display(token, result, labels) def update_module_display(self, token, result, labels): """更新模块显示内容""" # 示例实现:根据token和结果更新UI logger.info(f"模块 {token} 返回结果: {result}") # ---------- 事件订阅 ---------- def _setup_event_subscriptions(self): event_center.subscribe(EventType.MODULE_COMPLETE.value, self._handle_module_complete) event_center.subscribe(EventType.COMMAND_FROM_MAIN.value, self._handle_main_window_command) event_center.subscribe(EventType.RUN_COMMAND.value, self._handle_run_command) # 添加运行指令订阅 def _handle_module_complete(self, event): self.root.after(0, self.update_module_display, self.modules.get(event.source)) self.root.after(0, self.status_var.set, event.data.get('message', '分析完成')) def _handle_main_window_command(self, event): if event.target == 'ui': command = event.data.get('command') if command == 'switch_module': module_id = event.data.get('module_id') if module_id: self.root.after(0, self.select_module, module_id) elif command == 'update_status': message = event.data.get('message', '') self.root.after(0, self.status_var.set, message) def _handle_run_command(self, event): """处理运行指令事件""" if event.target not in self.modules: return # 通过事件中心发布运行指令到对应模块 run_event = Event( event_id=int(time.time()), event_type=EventType.RUN_COMMAND.value, source='main_ui', target=event.target, data=event.data, token=event.token ) event_center.publish(run_event)
最新发布
09-12
修改::已重新声明上文定义的无用法的 'publish',,重复的代码段(57 行长),,import logging import threading import uuid import time import weakref from enum import Enum, auto from typing import Dict, List, Callable, Optional, Any, Set, Union, Tuple from collections import defaultdict from dataclasses import dataclass, field from concurrent.futures import ThreadPoolExecutor # 初始化日志 logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @dataclass class Event: """事件类""" event_type: Union[str, 'EventType'] = field(repr=False) type: str = field(init=False) source: str target: Optional[str] = None event_id: str = field(default_factory=lambda: str(uuid.uuid4())) token: Optional[str] = None data: Dict[str, Any] = field(default_factory=dict) timestamp: float = field(default_factory=time.time) def __post_init__(self): if isinstance(self.event_type, EventType): self.type = self.event_type.name else: self.type = self.event_type if not isinstance(self.event_type, str) or not self.event_type: raise ValueError("event_type 必须是非空字符串或EventType枚举") if not isinstance(self.source, str) or not self.source: raise ValueError("source 必须是非空字符串") class EventType(Enum): """完整事件类型枚举""" # 系统事件 SYSTEM_STARTUP = auto() SYSTEM_SHUTDOWN = auto() MODULE_READY = auto() ERROR = auto() TEST_EVENT = auto() # 模块控制事件 MODULE_RUN = auto() COMMAND = auto() # 数据处理事件 DATA_SUBMIT = auto() DATA_UPDATE = auto() DATA_FREEZE = auto() DATA_ORGANIZE = auto() DATA_RESULT = auto() # 分析结果事件 ANALYSIS_RESULT = auto() INPUT_ANALYSIS_START = auto() INPUT_ANALYSIS_END = auto() COMBINATION_RESULT = auto() COMBINATION_ANALYSIS_START = auto() COMBINATION_ANALYSIS_END = auto() FOLLOW_RESULT = auto() FOLLOW_ANALYSIS_START = auto() FOLLOW_ANALYSIS_UPDATE = auto() TREND_ANALYSIS_RESULT = auto() TREND_ANALYSIS_REQUEST = auto() TREND_ANALYSIS_REPORT = auto() NUMBER_GENERATION_RESULT = auto() NUMBER_GENERATION_START = auto() NUMBER_GENERATION_FINISH = auto() # UI相关事件 UI_UPDATE = auto() DIALOG_OPEN = auto() DIALOG_CLOSE = auto() REGISTER_UI = auto() GET_RESULTS = auto() # 状态事件 LOADING_PROGRESS = auto() LOADING_COMPLETE = auto() # 特定功能事件 EXCLUDE_NUMBERS = auto() POOL_UPDATE = auto() # 模块标识事件 INPUT = auto() COMBINATION = auto() FOLLOW = auto() TREND = auto() GENERATION = auto() class EventCenter: """线程安全的事件中心(最终优化版)""" _instance = None _lock = threading.Lock() _executor = ThreadPoolExecutor(max_workers=10, thread_name_prefix="EventWorker") def __new__(cls): with cls._lock: if cls._instance is None: cls._instance = super().__new__(cls) cls._instance.__initialized = False return cls._instance def __init__(self): """初始化事件中心(单例模式)""" if getattr(self, '__initialized', False): return self._handlers = {} self._main_ui = lambda: None self.__initialized = True self._subscribers = defaultdict(list) self._event_history = {} self._pending_acks = set() self._ack_timeout = 5.0 self._stats = { 'total_events': 0, 'failed_events': 0, 'delivered_events': 0 } class EventCenter: def __init__(self): self.routing_config = {} self.subscribers = {} def set_routing_config(self, config): self.routing_config = config def publish(self, event_type, event_data): # 实现事件发布逻辑 pass def subscribe(self, event_type, subscriber, callback): # 实现事件订阅逻辑 pass # 主线程会把 MainInterface 实例注册进来 def set_main_ui(self, main_ui): self._main_ui = weakref.ref(main_ui) def publish(self, event): # ←--- 新增:如果事件是“需要主界面”的,而界面还没好,直接丢弃 if getattr(event, 'need_main_ui', False) and self._main_ui() is None: logger.debug('主界面未就位,事件 %s 被忽略', event.type) return # 下面保持你原来的分发逻辑 for handler in self._handlers.get(event.type, []): handler(event) def subscribe(self, event_type: Union[str, EventType], handler: Callable[[Event], None], token: Optional[str] = None) -> None: """订阅事件(支持token过滤)""" event_type_str = event_type.name if isinstance(event_type, EventType) else str(event_type) with self._lock: self._subscribers[event_type_str].append((handler, token)) logger.debug(f"已订阅事件: {event_type_str}, token: {token}") def unsubscribe(self, event_type: Union[str, EventType], handler: Callable[[Event], None]) -> bool: """取消订阅事件""" event_type_str = event_type.name if isinstance(event_type, EventType) else str(event_type) with self._lock: if event_type_str not in self._subscribers: return False before = len(self._subscribers[event_type_str]) self._subscribers[event_type_str] = [(h, t) for h, t in self._subscribers[event_type_str] if h != handler] removed = before != len(self._subscribers[event_type_str]) if removed: logger.debug(f"已取消订阅: {event_type_str}") return removed def publish(self, event: Event, require_ack: bool = False, async_handle: bool = True) -> bool: """发布事件(支持同步/异步处理)""" try: # 事件验证逻辑 if not hasattr(event, 'event_type') or not hasattr(event, 'source'): raise AttributeError("事件缺少必要属性: event_type或source") if not hasattr(event, 'event_id') or not event.event_id: event.event_id = str(uuid.uuid4()) if hasattr(event, '__post_init__'): event.__post_init__() # 主处理逻辑 with self._lock: if event.event_id in self._event_history: logger.warning(f"重复事件ID: {event.event_id}") return False self._event_history[event.event_id] = event self._stats['total_events'] += 1 if require_ack: self._pending_acks.add(event.event_id) handlers = self._get_matching_handlers(event) if not handlers: logger.debug(f"没有处理器订阅: {event.event_type}") return True if async_handle: self._executor.submit(self._dispatch_event, event, handlers, require_ack) else: self._dispatch_event(event, handlers, require_ack) return True except Exception as ex: logger.exception(f"事件处理失败: {ex}") with self._lock: self._stats['failed_events'] += 1 return False def _get_matching_handlers(self, event: Event) -> List[Callable[[Event], None]]: """获取匹配的事件处理器""" event_type_str = event.event_type.name if isinstance(event.event_type, EventType) else event.event_type with self._lock: return [h for h, t in self._subscribers.get(event_type_str, []) if t is None or t == event.token] def _dispatch_event(self, event: Event, handlers: List[Callable[[Event], None]], require_ack: bool) -> None: """分发事件到处理器""" for handler in handlers: try: handler(event) with self._lock: self._stats['delivered_events'] += 1 logger.debug(f"事件处理成功: {str(event.event_id)[:8]}") except Exception as ex: logger.exception(f"处理器异常: {ex}") if require_ack and event.target: self._wait_for_ack(event) def _wait_for_ack(self, event: Event) -> None: """等待事件确认""" start = time.time() while time.time() - start < self._ack_timeout: with self._lock: if event.event_id not in self._pending_acks: return time.sleep(0.05) logger.warning(f"事件确认超时: {event.event_id[:8]}") with self._lock: if event.event_id in self._pending_acks: self._pending_acks.remove(event.event_id) def get_stats(self) -> Dict[str, int]: """获取事件中心统计信息""" with self._lock: return self._stats.copy() def clear(self): """重置事件中心状态(测试专用)""" with self._lock: self._subscribers.clear() self._event_history.clear() self._pending_acks.clear() self._stats = { 'total_events': 0, 'failed_events': 0, 'delivered_events': 0 } # 全局单例实例 event_center = EventCenter()
09-12
修改::类 '_SpecialForm' 未定义 '__setitem__',所以不能对其实例使用 '[]' 运算符,,,重复的代码段(57 行长),,,代码# core/event_center.py import logging import threading import uuid import time from enum import Enum, auto from typing import Dict, List, Callable, Optional, Any, Set, DefaultDict, Union, Tuple from collections import defaultdict from dataclasses import dataclass, field from concurrent.futures import ThreadPoolExecutor # 初始化日志 logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @dataclass class Event: """事件数据类""" event_type: Union[str, 'EventType'] source: str target: Optional[str] = None event_id: str = field(default_factory=lambda: str(uuid.uuid4())) token: Optional[str] = None Optional[Dict[str, Any]] = field(default_factory=dict) timestamp: float = field(default_factory=time.time) def __post_init__(self): """数据验证和类型转换""" if isinstance(self.event_type, EventType): self.event_type = self.event_type.name if not isinstance(self.event_type, str) or not self.event_type: raise ValueError("event_type 必须是非空字符串或EventType枚举") if not isinstance(self.source, str) or not self.source: raise ValueError("source 必须是非空字符串") class EventType(Enum): """完整事件类型枚举""" # 系统事件 SYSTEM_STARTUP = auto() SYSTEM_SHUTDOWN = auto() MODULE_READY = auto() ERROR = auto() TEST_EVENT = auto() # 模块控制事件 MODULE_RUN = auto() COMMAND = auto() # 数据处理事件 DATA_SUBMIT = auto() DATA_UPDATE = auto() DATA_FREEZE = auto() DATA_ORGANIZE = auto() DATA_RESULT = auto() # 分析结果事件 ANALYSIS_RESULT = auto() INPUT_ANALYSIS_START = auto() INPUT_ANALYSIS_END = auto() COMBINATION_RESULT = auto() COMBINATION_ANALYSIS_START = auto() COMBINATION_ANALYSIS_END = auto() FOLLOW_RESULT = auto() FOLLOW_ANALYSIS_START = auto() FOLLOW_ANALYSIS_UPDATE = auto() TREND_ANALYSIS_RESULT = auto() TREND_ANALYSIS_REQUEST = auto() TREND_ANALYSIS_REPORT = auto() NUMBER_GENERATION_RESULT = auto() NUMBER_GENERATION_START = auto() NUMBER_GENERATION_FINISH = auto() # UI相关事件 UI_UPDATE = auto() DIALOG_OPEN = auto() DIALOG_CLOSE = auto() REGISTER_UI = auto() GET_RESULTS = auto() # 状态事件 LOADING_PROGRESS = auto() LOADING_COMPLETE = auto() # 特定功能事件 EXCLUDE_NUMBERS = auto() POOL_UPDATE = auto() # 模块标识事件 INPUT = auto() COMBINATION = auto() FOLLOW = auto() TREND = auto() GENERATION = auto() class EventCenter: """线程安全的事件中心(最终优化版)""" _instance = None _lock = threading.Lock() _executor = ThreadPoolExecutor(max_workers=10, thread_name_prefix="EventWorker") def __new__(cls): with cls._lock: if cls._instance is None: cls._instance = super().__new__(cls) cls._instance.__initialized = False return cls._instance def __init__(self): """初始化事件中心(单例模式)""" if getattr(self, '__initialized', False): return self.__initialized = True self._subscribers: DefaultDict[str, List[Tuple[Callable[[Event], None], Optional[str]]]] = defaultdict(list) self._event_history: Dict[str, Event] = {} self._pending_acks: Set[str] = set() self._ack_timeout = 5.0 self._stats = { 'total_events': 0, 'failed_events': 0, 'delivered_events': 0 } def subscribe(self, event_type: Union[str, EventType], handler: Callable[[Event], None], token: Optional[str] = None) -> None: """订阅事件(支持token过滤)""" event_type_str = event_type.name if isinstance(event_type, EventType) else str(event_type) with self._lock: self._subscribers[event_type_str].append((handler, token)) logger.debug(f"已订阅事件: {event_type_str}, token: {token}") def unsubscribe(self, event_type: Union[str, EventType], handler: Callable[[Event], None]) -> bool: """取消订阅事件""" event_type_str = event_type.name if isinstance(event_type, EventType) else str(event_type) with self._lock: if event_type_str not in self._subscribers: return False before = len(self._subscribers[event_type_str]) self._subscribers[event_type_str] = [(h, t) for h, t in self._subscribers[event_type_str] if h != handler] removed = before != len(self._subscribers[event_type_str]) if removed: logger.debug(f"已取消订阅: {event_type_str}") return removed def publish(self, event: Event, require_ack: bool = False, async_handle: bool = True) -> bool: """发布事件(支持同步/异步处理)""" # 增强事件验证 try: # 确保事件有必要的属性 if not hasattr(event, 'event_type') or not hasattr(event, 'source'): raise AttributeError("事件缺少必要属性: event_type或source") # 自动生成事件ID(如果缺失) if not hasattr(event, 'event_id') or not event.event_id: event.event_id = str(uuid.uuid4()) # 执行事件验证 if hasattr(event, '__post_init__'): event.__post_init__() else: # 手动验证基本属性 if not isinstance(event.event_type, (str, EventType)): raise TypeError("event_type必须是字符串或EventType") if not isinstance(event.source, str) or not event.source: raise ValueError("source必须是非空字符串") except (ValueError, TypeError, AttributeError) as ex: # 处理预期的验证错误 logger.error(f"事件验证失败: {ex}") with self._lock: self._stats['failed_events'] += 1 return False except Exception as ex: # 记录所有其他异常 logger.exception(f"事件验证过程中发生意外错误: {ex}") with self._lock: self._stats['failed_events'] += 1 return False # 主事件处理逻辑 try: with self._lock: if event.event_id in self._event_history: logger.warning(f"重复事件ID: {event.event_id}") return False self._event_history[event.event_id] = event self._stats['total_events'] += 1 if require_ack: self._pending_acks.add(event.event_id) handlers = self._get_matching_handlers(event) if not handlers: logger.debug(f"没有处理器订阅: {event.event_type}") return True if async_handle: self._executor.submit(self._dispatch_event, event, handlers, require_ack) else: self._dispatch_event(event, handlers, require_ack) return True except (KeyError, AttributeError) as ex: # 处理内部数据结构错误 logger.error(f"内部数据结构错误: {ex}") with self._lock: self._stats['failed_events'] += 1 return False except Exception as ex: # 捕获所有其他异常 logger.exception(f"发布事件时发生未预期错误: {ex}") with self._lock: self._stats['failed_events'] += 1 return False def _get_matching_handlers(self, event: Event) -> List[Callable[[Event], None]]: """获取匹配的事件处理器""" event_type_str = event.event_type.name if isinstance(event.event_type, EventType) else event.event_type with self._lock: return [h for h, t in self._subscribers.get(event_type_str, []) if t is None or t == event.token] def _dispatch_event(self, event: Event, handlers: List[Callable[[Event], None]], require_ack: bool) -> None: """分发事件到处理器""" for handler in handlers: try: handler(event) with self._lock: self._stats['delivered_events'] += 1 logger.debug(f"事件处理成功: {str(event.event_id)[:8]}") except Exception as ex: logger.exception(f"处理器异常: {ex}") if require_ack and event.target: self._wait_for_ack(event) def _wait_for_ack(self, event: Event) -> None: """等待事件确认""" start = time.time() while time.time() - start < self._ack_timeout: with self._lock: if event.event_id not in self._pending_acks: return time.sleep(0.05) logger.warning(f"事件确认超时: {event.event_id[:8]}") with self._lock: if event.event_id in self._pending_acks: self._pending_acks.remove(event.event_id) def get_stats(self) -> Dict[str, int]: """获取事件中心统计信息""" with self._lock: return self._stats.copy() def clear(self): """重置事件中心状态(测试专用)""" with self._lock: self._subscribers.clear() self._event_history.clear() self._pending_acks.clear() self._stats = { 'total_events': 0, 'failed_events': 0, 'delivered_events': 0 } # 全局单例实例 event_center = EventCenter()
09-04
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值