class Signals(QObject):
def __init__(self, dic: dict = None):
super().__init__()
# 信号字典,格式为:{signal_name: (signal, default_data, include_in_emit_all)}
self._signals: dict = {}
for k, v in (dic or {}).items():
self.__setattr__(k, v)
def __setattr__(self, attr: str, value) -> None:
if attr == '_signals':
super().__setattr__(attr, value)
return
if isinstance(value, pyqtSignal):
self._signals[attr] = (value, None, True)
elif isinstance(value, tuple) and len(value) >= 3 and isinstance(value[0], pyqtSignal):
self._signals[attr] = (value[0], value[1], value[2])
else:
super().__setattr__(attr, value)
def __getattr__(self, attr: str):
signal, _, _ = self._signals.get(attr, (None, None, None))
if signal is None:
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{attr}'")
return signal
def __setitem__(self, key: str, value) -> None:
self.__setattr__(key, value)
def __getitem__(self, key: str):
return self.__getattr__(key)
def __iter__(self):
return iter(self._signals.items())
def emit(self, signal_name: str, message=None) -> None:
signal, default_data, _ = self._signals.get(signal_name, (None, None, None))
if signal is None:
raise KeyError(f"'{self.__class__.__name__}' object has no signal '{signal_name}'")
if default_data is None:
signal.emit()
else:
signal.emit(message if message is not None else default_data)
def connect(self, signal_name: str, slot) -> None:
signal, _, _ = self._signals.get(signal_name, (None, None, None))
if signal is None:
raise KeyError(f"'{self.__class__.__name__}' object has no signal '{signal_name}'")
signal.connect(slot)
logger.info(f"Signal '{signal_name}' connected to slot '{slot.__name__}'")
def disconnect(self, signal_name: str, slot) -> None:
signal, _, _ = self._signals.get(signal_name, (None, None, True))
if signal is None:
raise KeyError(f"'{self.__class__.__name__}' object has no signal '{signal_name}'")
signal.disconnect(slot)
logger.info(f"Signal '{signal_name}' disconnected from slot '{slot.__name__}'")
def get_signal_data(self, signal_name: str):
_, default_data, _ = self._signals.get(signal_name, (None, None, True))
return default_data
def set_signal_data(self, signal_name: str, data) -> None:
if signal_name in self._signals:
self._signals[signal_name] = (self._signals[signal_name][0], data, True)
else:
raise KeyError(f"'{self.__class__.__name__}' object has no signal '{signal_name}'")
def emit_all(self) -> None:
for signal_name, (signal, default_data, include_in_emit_all) in self._signals.items():
if include_in_emit_all:
if default_data is None:
signal.emit()
else:
signal.emit(default_data)
def create_signal(self, signal_name: str, signal: pyqtSignal, default_data=None, include_in_emit_all=True) -> None:
if signal_name not in self._signals:
self._signals[signal_name] = (signal, default_data, include_in_emit_all)
logger.info(f"Signal '{signal_name}' created")
else:
logger.warning(f"Signal '{signal_name}' already exists")
使用signals.result_ready.connect(on_result_ready)
会报错AttributeError: 'PyQt5.QtCore.pyqtSignal' object has no attribute 'connect'