# -*- coding: utf-8 -*- """ 事件模块完整演示 ───────────────────────────────────────────────────────────────── 运行: python main.py 依赖: pip install PyQt5 ───────────────────────────────────────────────────────────────── """ import logging from PyQt5.QtCore import Qt, pyqtSlot from PyQt5.QtGui import QColor, QFont from PyQt5.QtWidgets import ( QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QTextEdit, QLabel, QPushButton, QTableWidget, QHeaderView, QSplitter, QGroupBox, QStatusBar ) from uas.event_bus import event_bus from uas.event_model import Event, EventState, make_event # ── 事件模块 ────────────────────────────────────────────────────── from uas.event_type import EventType, event_registry # ── 处理器(触发 @on_event 注册)──────────────────────────────── from handlers.device_handlers import ( DeviceErrorHandler, DeviceTimeoutHandler, EquipmentFaultHandler, ) logging.basicConfig( level = logging.DEBUG, format = "%(asctime)s [%(levelname)-8s] %(name)s - %(message)s", ) logger = logging.getLogger("main") # ───────────────────────────────────────────────────────────────── # 主窗口 # ───────────────────────────────────────────────────────────────── class EventMonitorWindow(QMainWindow): # 状态颜色映射 STATE_COLORS = { EventState.HANDLED: QColor("#4CAF50"), EventState.FAILED: QColor("#f44336"), EventState.CANCELLED: QColor("#FF9800"), EventState.IGNORED: QColor("#9E9E9E"), EventState.PROCESSING: QColor("#2196F3"), EventState.PENDING: QColor("#607D8B"), } def __init__(self): super().__init__() self.setWindowTitle("🛰️ 事件监控系统 — PyQt5 EventBus 演示") self.resize(1200, 750) self._setup_bus() self._setup_ui() self._start_demo() # ── 总线初始化 ──────────────────────────────────────────────── def _setup_bus(self): # 注册类处理器 event_bus.register_handler(DeviceErrorHandler()) event_bus.register_handler(DeviceTimeoutHandler()) event_bus.register_handler(EquipmentFaultHandler()) # 扫描 @on_event 装饰器处理器 count = event_bus.scan_decorators() logger.info(f"扫描到 {count} 个装饰器处理器") # 动态注册自定义事件类型 event_registry.register( "sensor.overflow", category = "device", description = "传感器数据溢出", cancellable = True, ) # 连接总线信号到 UI 槽 event_bus.event_submitted.connect(self._on_event_submitted) event_bus.event_handled.connect(self._on_event_handled) event_bus.event_failed.connect(self._on_event_failed) event_bus.event_ignored.connect(self._on_event_ignored) event_bus.stats_updated.connect(self._on_stats_updated) # ── UI 构建 ─────────────────────────────────────────────────── def _setup_ui(self): central = QWidget() self.setCentralWidget(central) root = QVBoxLayout(central) root.setContentsMargins(6, 6, 6, 6) splitter = QSplitter(Qt.Horizontal) # ── 左侧:控制面板 ──────────────────────────────────────── left = QWidget() left_layout = QVBoxLayout(left) # 统计卡片 stats_group = QGroupBox("📊 实时统计") stats_layout = QHBoxLayout(stats_group) self._lbl_total = self._stat_label("总计", "0", "#2196F3") self._lbl_handled = self._stat_label("已处理", "0", "#4CAF50") self._lbl_failed = self._stat_label("失败", "0", "#f44336") stats_layout.addWidget(self._lbl_total) stats_layout.addWidget(self._lbl_handled) stats_layout.addWidget(self._lbl_failed) left_layout.addWidget(stats_group) # 事件触发按钮 btn_group = QGroupBox("🎯 触发事件") btn_layout = QVBoxLayout(btn_group) buttons = [ ("🔴 设备错误 (E001)", self._fire_device_error), ("⚠️ 设备警告 (高温)", self._fire_device_warning), ("⏱️ 设备超时", self._fire_device_timeout), ("⚙️ 装备故障 (critical)",self._fire_equipment_fault), ("🟢 设备连接", self._fire_device_connected), ("✅ 装备恢复", self._fire_equipment_recovered), ("💓 系统心跳", self._fire_heartbeat), ("🔧 自定义事件", self._fire_custom_event), ("💥 紧急停机 (E999)", self._fire_emergency), ] for text, slot in buttons: btn = QPushButton(text) btn.setMinimumHeight(32) btn.clicked.connect(slot) btn_layout.addWidget(btn) left_layout.addWidget(btn_group) # 批量测试 batch_btn = QPushButton("🚀 批量压测 (50个事件)") batch_btn.setStyleSheet("background:#673AB7; color:white; font-weight:bold;") batch_btn.clicked.connect(self._fire_batch) left_layout.addWidget(batch_btn) left_layout.addStretch() splitter.addWidget(left) # ── 右侧:事件列表 + 日志 ───────────────────────────────── right = QWidget() right_layout = QVBoxLayout(right) # 事件表格 table_group = QGroupBox("📋 事件记录") table_layout = QVBoxLayout(table_group) self._table = QTableWidget(0, 6) self._table.setHorizontalHeaderLabels( ["时间", "事件类型", "来源", "优先级", "状态", "消息"] ) self._table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self._table.setAlternatingRowColors(True) self._table.setEditTriggers(QTableWidget.NoEditTriggers) self._table.setSelectionBehavior(QTableWidget.SelectRows) table_layout.addWidget(self._table) right_layout.addWidget(table_group, stretch=2) # 日志输出 log_group = QGroupBox("📝 处理日志") log_layout = QVBoxLayout(log_group) self._log_edit = QTextEdit() self._log_edit.setReadOnly(True) self._log_edit.setFont(QFont("Consolas", 10)) self._log_edit.setStyleSheet( "background:#1e1e1e; color:#d4d4d4; border-radius:4px;" ) log_layout.addWidget(self._log_edit) right_layout.addWidget(log_group, stretch=1) splitter.addWidget(right) splitter.setSizes([280, 900]) root.addWidget(splitter) # 状态栏 self._statusbar = QStatusBar() self.setStatusBar(self._statusbar) self._statusbar.showMessage("就绪 | EventBus 运行中") def _stat_label(self, title: str, value: str, color: str) -> QLabel: lbl = QLabel(f"