Gambas3 Qt5 TextEdit设置RichText后光标跳末尾如何解决
Gambas3 Qt5 TextEdit 富文本编辑光标跳转问题修复
问题复现
在Gambas3中使用Qt5 TextEdit控件实现富文本彩色输入功能时,原有代码如下:
Dim cursorpos As Integer If Key.Code = Key.Left Or Key.Code = Key.Up Or Key.code = Key.Right Or Key.Code = Key.Down Or Key.Code = Key.Delete Or Key.Code = Key.Backspace Then cursorpos = TextEdit1.Pos ' 记录光标位置 Print cursorpos Else cursorpos = TextEdit1.Pos Print cursorpos TextEdit1.RichText = "<font color = \"#224444\">" & Replace(TextEdit1.Text, gb.NewLine, "<br>") & "</font>" ' 替换换行为<br>标签套字体颜色 Print "setting : ", cursorpos ' 打印值正确 TextEdit1.Pos = cursorpos ' 赋值不生效 Print "got : ", TextEdit1.Pos ' 光标直接跳转到字符串末尾 Endif
测试操作流程:
- 编辑器内输入两行测试文本:
This si a line this is a second line
- 用方向键移动光标到第一行笔误位置,按两次退格删除错误内容
si,该步骤操作正常 - 输入字符"i"时,预期光标停留在刚输入的"i"后方,实际直接跳转到整个文本的最末尾
问题原因
整体给RichText属性赋值时,控件会完全重建内部的富文本文档结构:
- 拼接的
<font>、<br>等HTML标签会占用富文本内部的字符计数,但这些标签不会显示在编辑区,之前记录的纯文本光标位置和富文本内部位置不匹配 - 赋值
RichText后控件需要时间完成文档渲染,立刻设置Pos属性的操作会被控件默认的“重建文档后光标移到末尾”的逻辑覆盖,所以赋值不生效
修复方案
推荐方案:不要全量重写RichText,用原生光标接口设置样式
从根源上避免全量重建文档,通过TextCursor接口直接给输入的内容设置颜色,不会触发光标跳转,性能也更好:
Public Sub TextEdit1_KeyPress() ' 方向键、删除类按键不需要额外处理,走默认逻辑即可 If Key.Code = Key.Left Or Key.Code = Key.Up Or Key.Code = Key.Right Or Key.Code = Key.Down Or Key.Code = Key.Delete Or Key.Code = Key.BackSpace Then Return ' 拦截默认输入,手动插入字符并设置样式 Stop Event Dim hCursor As TextCursor = TextEdit1.Cursor ' 插入当前按下的字符 hCursor.Insert(Chr(Key.Text)) ' 选中刚插入的单个字符 hCursor.MoveStart(-1) ' 设置对应颜色 #224444 hCursor.ForeColor = Color.RGB(34, 68, 68) ' 取消选中,光标移动到刚输入字符的后方 hCursor.MoveEnd() End
兼容方案(不推荐):延迟设置光标+计算标签偏移
如果必须保留全量赋值RichText的逻辑,需要等控件完成文档渲染后,加上HTML标签的固定偏移量再设置光标位置,需要额外加一个短延迟定时器:
Dim cursorpos As Integer ' 提前计算前置标签的固定长度:<font color = "#224444"> 共24个字符 Const TAG_OFFSET As Integer = 24 Public Sub TextEdit1_KeyPress() If Key.Code = Key.Left Or Key.Code = Key.Up Or Key.code = Key.Right Or Key.Code = Key.Down Or Key.Code = Key.Delete Or Key.Code = Key.Backspace Then cursorpos = TextEdit1.Pos Else cursorpos = TextEdit1.Pos TextEdit1.RichText = "<font color = \"#224444\">" & Replace(TextEdit1.Text, gb.NewLine, "<br>") & "</font>" ' 启动10ms延迟定时器,等文档渲染完成后再恢复光标 tmrRestorePos.Delay = 10 tmrRestorePos.Start Endif End Public Sub tmrRestorePos_Timer() ' 原光标位置加上前置标签的偏移量,才是富文本文档里的正确位置 TextEdit1.Pos = cursorpos + TAG_OFFSET tmrRestorePos.Stop End
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

