jiateng_ws/utils/focus_tracker.py

111 lines
4.3 KiB
Python
Raw Normal View History

from PySide6.QtWidgets import QApplication, QLineEdit, QComboBox
from PySide6.QtCore import QObject, Signal
import logging
class FocusTracker(QObject):
"""焦点跟踪器,用于跟踪当前焦点所在的输入框"""
# 定义单例
_instance = None
# 信号:当焦点变化时触发
focus_changed = Signal(object)
@classmethod
def get_instance(cls):
"""获取单例实例"""
if cls._instance is None:
cls._instance = FocusTracker()
return cls._instance
def __init__(self):
"""初始化焦点跟踪器"""
if FocusTracker._instance is not None:
raise Exception("FocusTracker是单例类请使用get_instance()方法获取实例")
super().__init__()
self._current_focus = None
self._initialized = False
def initialize(self):
"""初始化焦点跟踪"""
if self._initialized:
return
# 连接应用程序的焦点变化信号
app = QApplication.instance()
if app:
app.focusChanged.connect(self._on_focus_changed)
self._initialized = True
logging.info("焦点跟踪器已初始化")
else:
logging.error("无法获取QApplication实例焦点跟踪器初始化失败")
def _on_focus_changed(self, old, now):
"""焦点变化处理"""
# 关注QLineEdit和QComboBox控件
if isinstance(now, (QLineEdit, QComboBox)):
self._current_focus = now
self.focus_changed.emit(now)
widget_type = "输入框" if isinstance(now, QLineEdit) else "下拉框"
logging.debug(f"焦点变化到{widget_type}: {now.objectName()}")
def get_current_focus(self):
"""获取当前焦点所在的控件"""
return self._current_focus
def set_text_and_trigger_enter(self, text):
"""设置当前焦点控件的文本并触发回车事件"""
if not self._current_focus:
logging.warning("当前没有焦点控件,无法设置文本和触发回车事件")
return False
# 创建回车键事件
from PySide6.QtGui import QKeyEvent
from PySide6.QtCore import Qt, QEvent
key_event = QKeyEvent(QEvent.KeyPress, Qt.Key_Return, Qt.NoModifier)
# 根据控件类型处理
if isinstance(self._current_focus, QLineEdit):
# 设置文本
self._current_focus.setText(text)
# 发送事件到当前焦点控件
QApplication.sendEvent(self._current_focus, key_event)
logging.info(f"已将文本 '{text}' 设置到输入框并触发回车事件")
return True
elif isinstance(self._current_focus, QComboBox):
# 对于ComboBox先查找匹配的项
combo_box = self._current_focus
# 查找完全匹配的项
index = combo_box.findText(text)
if index >= 0:
combo_box.setCurrentIndex(index)
logging.info(f"已在下拉框中选择匹配项: '{text}'")
else:
# 如果没有完全匹配的项设置为编辑文本如果ComboBox是可编辑的
if combo_box.isEditable():
combo_box.setEditText(text)
logging.info(f"已将文本 '{text}' 设置到可编辑下拉框")
else:
logging.warning(f"下拉框中没有匹配项 '{text}',且下拉框不可编辑")
return False
# 发送事件到当前焦点控件
QApplication.sendEvent(combo_box, key_event)
# 如果ComboBox有activated信号手动触发
try:
if hasattr(combo_box, 'activated'):
combo_box.activated.emit(combo_box.currentIndex())
logging.debug("已触发下拉框的activated信号")
except Exception as e:
logging.error(f"触发下拉框activated信号失败: {e}")
return True
else:
logging.warning(f"不支持的控件类型: {type(self._current_focus)}")
return False