111 lines
4.3 KiB
Python
111 lines
4.3 KiB
Python
|
|
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
|