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

如何在这款基于PyQt5实现的文本编辑器中添加行号

给PyQt5文本编辑器添加行号功能的实现方案

嘿,我来帮你搞定这个行号功能!在PyQt5里给文本编辑器加行号,最常用的方式是给QPlainTextEdit(如果你的UI里是QTextEdit也可以类似处理,但QPlainTextEdit更适合代码类编辑)搭配一个自定义的行号侧边栏,然后通过信号同步更新行号和滚动状态。下面是结合你的现有代码的具体实现步骤:

步骤1:修改你的类,添加行号栏相关代码

首先,我们需要在你的MyApp类里添加行号栏的创建、信号关联以及绘制逻辑。这里假设你UI里的文本编辑控件名为textEdit(如果你的控件名字不一样,记得替换成实际的):

import sys
from PyQt5.QtCore import Qt, QRect, QPoint
from PyQt5.QtWidgets import QMainWindow, QApplication, QAction, QWidget, QPlainTextEdit
from PyQt5.QtGui import QPainter, QColor, QFont
from PyQt5 import uic

Ui_MainWindow, QtBaseClass = uic.loadUiType('EditorUI.ui')

class LineNumberArea(QWidget):
    def __init__(self, editor):
        super().__init__(editor)
        self.code_editor = editor

    def sizeHint(self):
        # 设置行号栏的宽度
        return QSize(self.code_editor.line_number_area_width(), 0)

    def paintEvent(self, event):
        # 绘制行号
        self.code_editor.line_number_area_paint_event(event)

class MyApp(QMainWindow, Ui_MainWindow):
    def __init__(self):
        self.newLines = 1
        super(MyApp, self).__init__(None)
        self.setupUi(self)  # 别忘了调用setupUi加载UI元素
        
        # 初始化行号栏
        self.line_number_area = LineNumberArea(self.textEdit)
        # 关联文本编辑的信号,触发行号更新
        self.textEdit.blockCountChanged.connect(self.update_line_number_area_width)
        self.textEdit.updateRequest.connect(self.update_line_number_area)
        self.textEdit.verticalScrollBar().valueChanged.connect(self.line_number_area.update)
        
        # 初始更新行号栏宽度
        self.update_line_number_area_width(0)

    def line_number_area_width(self):
        # 计算行号栏的宽度,根据最大行数的位数调整
        digits = 1
        max_num = max(1, self.textEdit.blockCount())
        while max_num >= 10:
            max_num /= 10
            digits += 1
        space = 3 + self.textEdit.fontMetrics().horizontalAdvance('9') * digits
        return space

    def update_line_number_area_width(self, _):
        # 调整文本编辑区的边距,给行号栏留出空间
        self.textEdit.setViewportMargins(self.line_number_area_width(), 0, 0, 0)

    def update_line_number_area(self, rect, dy):
        # 更新行号栏的显示区域
        if dy:
            self.line_number_area.scroll(0, dy)
        else:
            self.line_number_area.update(0, rect.y(), self.line_number_area.width(), rect.height())
        if rect.contains(self.textEdit.viewport().rect()):
            self.update_line_number_area_width(0)

    def line_number_area_paint_event(self, event):
        # 绘制行号的具体逻辑
        painter = QPainter(self.line_number_area)
        # 设置行号栏背景色
        painter.fillRect(event.rect(), QColor(240, 240, 240))
        
        block = self.textEdit.firstVisibleBlock()
        block_number = block.blockNumber()
        top = self.textEdit.blockBoundingGeometry(block).translated(self.textEdit.contentOffset()).top()
        bottom = top + self.textEdit.blockBoundingRect(block).height()

        # 匹配文本编辑区的字体
        font = self.textEdit.font()
        font.setBold(True)
        painter.setFont(font)
        painter.setPen(QColor(120, 120, 120))

        while block.isValid() and top <= event.rect().bottom():
            if block.isVisible() and bottom >= event.rect().top():
                number = str(block_number + 1)
                painter.drawText(0, int(top), self.line_number_area.width() - 5, self.textEdit.fontMetrics().height(),
                                Qt.AlignRight, number)

            block = block.next()
            top = bottom
            bottom = top + self.textEdit.blockBoundingRect(block).height()
            block_number += 1

    # 你的原有代码(比如菜单、New Action等)继续保留在这里
    # ...

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

步骤2:关键逻辑说明

  • 自定义LineNumberArea类:这个类负责行号的绘制,它作为文本编辑区的子控件存在,确保和编辑器同步布局。
  • 信号关联:
    • blockCountChanged:当文本的行数变化时,自动调整行号栏的宽度(比如行数从9变成10,需要多一位数字的宽度)。
    • updateRequest:当文本编辑区滚动或内容更新时,同步刷新行号栏的显示区域。
    • 滚动条的valueChanged信号:保证行号栏和文本编辑区的滚动位置完全一致。
  • 绘制逻辑:在line_number_area_paint_event里,我们遍历可见的文本块,绘制对应的行号,同时匹配文本编辑区的字体样式,保证视觉上的统一感。

注意事项

  1. 如果你的UI里的文本编辑控件是QTextEdit而非QPlainTextEdit,代码大部分可以复用,但blockBoundingGeometry等方法需要调整,建议换成QPlainTextEdit更适合做代码编辑器场景。
  2. 你可以根据自己的喜好修改行号栏的样式:比如调整背景色、字体颜色、行号与文本的间距等,只需要修改绘制部分的颜色参数和坐标即可。

内容的提问来源于stack exchange,提问作者Nikhil.Nixel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:18:17