You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 12:24:05