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

PySide6中QPlainTextEdit移动光标后滚动条长度异常问题

QPlainTextEdit超长行滚动异常问题解决方案

问题描述

Windows 10系统下使用PySide6开发时,QPlainTextEdit组件出现以下异常:

  • 设置包含超长行的文本后,将光标定位至第3行,初始显示正常
  • 向上滚动时,滚动条长度突然变短,视图直接跳至文本顶部,但光标仍停留在第3行

尝试过的无效方法:

  • 仅将垂直滚动条设为0:滚动条长度恢复正常,但视图默认显示文本顶部
  • 先记录滚动条位置、滚动至顶部再恢复原位置:无法解决滚动条长度异常问题

复现代码

import sys

from PySide6.QtGui import QTextCursor
from PySide6.QtWidgets import (
    QApplication,
    QMainWindow,
    QPlainTextEdit,
)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setGeometry(100, 100, 600, 400)
        self.textEdit = QPlainTextEdit(self)

        self.textEdit.setPlainText(
            f"Line 1 {'aaa ' * 1000}\n"
            "Line 2\n"
            "Line 3\n"
            "Line 4\n"
            "Line 5\n"
            f"Line 6 {'aaa ' * 1000}\n"
        )

        cursor = self.textEdit.textCursor()
        cursor.movePosition(QTextCursor.Start)
        # Move cursor to line 3
        cursor.movePosition(QTextCursor.Down, QTextCursor.MoveAnchor, 3 - 1)
        self.textEdit.setTextCursor(cursor)

        # scrollbarPosition = self.textEdit.verticalScrollBar().value()
        # self.textEdit.verticalScrollBar().setValue(0)
        # self.textEdit.verticalScrollBar().setValue(scrollbarPosition)

        self.setCentralWidget(self.textEdit)

app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

解决方案

通过强制触发视图布局计算,并手动定位滚动位置,解决超长行导致的滚动异常:

修改后的代码

import sys

from PySide6.QtGui import QTextCursor
from PySide6.QtWidgets import (
    QApplication,
    QMainWindow,
    QPlainTextEdit,
)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setGeometry(100, 100, 600, 400)
        self.textEdit = QPlainTextEdit(self)

        self.textEdit.setPlainText(
            f"Line 1 {'aaa ' * 1000}\n"
            "Line 2\n"
            "Line 3\n"
            "Line 4\n"
            "Line 5\n"
            f"Line 6 {'aaa ' * 1000}\n"
        )

        cursor = self.textEdit.textCursor()
        cursor.movePosition(QTextCursor.Start)
        # Move cursor to line 3
        cursor.movePosition(QTextCursor.Down, QTextCursor.MoveAnchor, 3 - 1)
        self.textEdit.setTextCursor(cursor)

        # 解决滚动异常的关键代码
        self.textEdit.ensureCursorVisible()
        # 获取目标行的顶部位置并设置滚动条
        block_geom = self.textEdit.blockBoundingGeometry(cursor.block())
        content_offset = self.textEdit.contentOffset()
        scroll_top = block_geom.translated(content_offset).top()
        self.textEdit.verticalScrollBar().setValue(int(scroll_top))

        self.setCentralWidget(self.textEdit)

app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

原理说明

  1. ensureCursorVisible()会触发QPlainTextEdit重新计算文本布局,修正超长行导致的滚动条范围计算错误
  2. 手动获取目标行的顶部坐标并设置滚动条位置,确保初始视图准确定位到第3行,同时滚动条的长度和范围恢复正常,后续滚动操作不会再出现跳顶异常

内容的提问来源于stack exchange,提问作者IssaRice

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:43:26