PyQt5 QTextEdit中WordUnderCursor异常,光标未在文字上也检测到单词
问题根本原因
这个现象不是WordUnderCursor功能异常,是Qt中cursorForPosition方法的默认设计:当你传入的鼠标坐标不在文档的实际文本区域内时,会自动返回距离该坐标最近的有效文本光标:
- 鼠标坐标在所有文本上方 → 返回文档起始位置的光标,选中第一个单词
- 鼠标坐标在所有文本下方 → 返回文档末尾位置的光标,选中最后一个单词
你没有对坐标的有效性做校验,直接执行选词逻辑,就会出现你描述的问题。
修复方案
除了增加坐标有效性校验外,你原有的高亮逻辑也存在严重问题:通过占位符替换+setHtml的方式会直接修改原文档内容、丢失原有格式、触发不必要的重绘,还会导致光标位置偏移,建议用QTextEdit自带的extraSelections实现临时高亮,完全不会改动原文档。
修复后的完整代码如下:
from PyQt5.QtWidgets import QTextEdit, QMainWindow, QApplication from PyQt5.QtGui import QMouseEvent, QTextCursor, QColor, QFont class Editor(QTextEdit): def __init__(self): super(Editor, self).__init__() self.setMouseTracking(True) def mouseMoveEvent(self, mouse_event: QMouseEvent) -> None: if not self.underMouse(): return super().mouseMoveEvent(mouse_event) # 获取位置对应的光标 text_cursor = self.cursorForPosition(mouse_event.pos()) # 校验:判断鼠标位置是否真的在当前光标对应的字符区域内 cursor_rect = self.cursorRect(text_cursor) if not cursor_rect.contains(mouse_event.pos()): # 不在有效文本区域,清除高亮直接返回 self.setExtraSelections([]) return super().mouseMoveEvent(mouse_event) # 选光标下的单词 text_cursor.select(QTextCursor.WordUnderCursor) word_under_cursor = text_cursor.selectedText() if not word_under_cursor.strip(): self.setExtraSelections([]) return super().mouseMoveEvent(mouse_event) print(word_under_cursor) # 用extraSelections实现临时高亮,不修改原文档 highlight_selection = QTextEdit.ExtraSelection() highlight_selection.format.setBackground(QColor("#FFFF00")) highlight_selection.format.setFontWeight(QFont.Bold) highlight_selection.cursor = text_cursor self.setExtraSelections([highlight_selection]) return super().mouseMoveEvent(mouse_event) def set_up(main_window): title_editor = Editor() title_editor.setText('Venda quente original xiaomi redmi airdots 2 tws fones de ouvido sem fio bluetooth fones controle ai gaming headset come') main_window.setCentralWidget(title_editor) main_window.show() application = QApplication([]) window = QMainWindow() set_up(window) application.exec()
内容的提问来源于stack exchange,提问作者José Guedes
相关产品推荐
相关产品推荐

