Pyqt5实现带行号显示的QTextEdit

Pyqt5实现带行号显示的QTextEdit

前言

自研自动化测试工具IDE界面需要添加行号显示并支持富文本显示,网上代码多为QPlainEdit实现行号显示,不支持富文本显示。

参考QT官方示例Code Edit Example(基于QPlainEdit),csdn(QPlainEdit)1以及StackOverflow2,改写代码实现带行号显示的富文本编辑窗口。

源码

代码已自测通过。

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import sys

from PyQt5.QtCore import Qt, QRect, QSize, QPoint
from PyQt5.QtGui import QPainter, QFont
from PyQt5.QtWidgets import QTextEdit, QApplication
from PyQt5.QtWidgets import QWidget


class QTextEditWithLineNum(QTextEdit):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setFont(QFont("Microsoft YaHei", 20, 2))
        self.setLineWrapMode(QTextEdit.NoWrap)  # 不自动换行
        self.lineNumberArea = LineNumPaint(self)
        self.document().blockCountChanged.connect(self.update_line_num_width)
        self.verticalScrollBar().valueChanged.connect(self.lineNumberArea.update)
        self.textChanged.connect(self.lineNumberArea.update)
        self.cursorPositionChanged.connect(self.lineNumberArea.update)
        self.update_line_num_width()

    def lineNumberAreaWidth(self):
        block_count = self.document().blockCount()
        max_value = max(1, block_count)
        d_count = len(str(max_value))
        _width = self.fontMetrics().width('9') * d_count + 5
        return _width

    def update_line_num_width(self):
        self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        cr = self.contentsRect()
        self.lineNumberArea.setGeometry(QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height()))

    def lineNumberAreaPaintEvent(self, event):
        painter = QPainter(self.lineNumberArea)
        painter.fillRect(event.rect(), Qt.lightGray)
        # 获取首个可见文本块
        first_visible_block_number = self.cursorForPosition(QPoint(0, 1)).blockNumber()
        # 从首个文本块开始处理
        blockNumber = first_visible_block_number
        block = self.document().findBlockByNumber(blockNumber)
        top = self.viewport().geometry().top()
        if blockNumber == 0:
            additional_margin = int(self.document().documentMargin() - 1 - self.verticalScrollBar().sliderPosition())
        else:
            prev_block = self.document().findBlockByNumber(blockNumber - 1)
            additional_margin = int(self.document().documentLayout().blockBoundingRect(
                prev_block).bottom()) - self.verticalScrollBar().sliderPosition()
        top += additional_margin
        bottom = top + int(self.document().documentLayout().blockBoundingRect(block).height())
        last_block_number = self.cursorForPosition(QPoint(0, self.height() - 1)).blockNumber()
        height = self.fontMetrics().height()
        while block.isValid() and (top <= event.rect().bottom()) and blockNumber <= last_block_number:
            if block.isVisible() and bottom >= event.rect().top():
                number = str(blockNumber + 1)
                painter.setPen(Qt.black)
                painter.drawText(0, top, self.lineNumberArea.width(), height, Qt.AlignCenter, number)
            block = block.next()
            top = bottom
            bottom = top + int(self.document().documentLayout().blockBoundingRect(block).height())
            blockNumber += 1


class LineNumPaint(QWidget):
    def __init__(self, q_edit):
        super().__init__(q_edit)
        self.q_edit_line_num = q_edit

    def sizeHint(self):
        return QSize(self.q_edit_line_num.lineNumberAreaWidth(), 0)

    def paintEvent(self, event):
        self.q_edit_line_num.lineNumberAreaPaintEvent(event)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    codeEditor = QTextEditWithLineNum()
    codeEditor.setGeometry(100, 100, 800, 600)
    codeEditor.show()
    sys.exit(app.exec_())

结果展示

实现效果


将行号显示部分代码加入到原有功能,成功实现功能较为完整的测试脚本IDE编辑窗口。
完整效果
相关代码后续慢慢更新至python自动化测试工具开发


  1. csdn参考文章 ↩︎

  2. StackOverflow参考链接 ↩︎

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyQt5可以通过使用Qt Designer来设计GUI界面,也可以通过编写Python代码来实现。 如果你想使用Qt Designer来设计GUI界面,可以按照以下步骤: 1. 安装Qt Designer:在终端中输入以下命令:`sudo apt-get install qttools5-dev-tools`(适用于Ubuntu系统),或者在Qt官网上下载Qt Designer软件包。 2. 设计GUI界面:打开Qt Designer,选择你想要的控件,拖拽到界面上,并进行布局和设置属性等操作。 3. 导出UI文件:设计完成后,保存成.ui文件,例如:`mainwindow.ui`。 4. 将UI文件转换成Python代码:在终端中输入以下命令:`pyuic5 -x mainwindow.ui -o mainwindow.py`,这将自动生成对应的Python代码,例如:`mainwindow.py`。 5. 在Python代码中调用UI文件:在Python代码中导入mainwindow.py文件,并使用其中的类来构建GUI界面。 如果你想通过编写Python代码来实现GUI界面,可以按照以下步骤: 1. 导入PyQt5模块:在Python代码中,使用`import PyQt5.QtWidgets`语句导入PyQt5模块。 2. 创建应用程序对象:使用`app = QtWidgets.QApplication(sys.argv)`语句创建应用程序对象。 3. 创建窗口对象:使用`win = QtWidgets.QMainWindow()`语句创建窗口对象。 4. 添加控件:使用`win.setCentralWidget(widget)`语句将控件添加到窗口中。 5. 显示窗口:使用`win.show()`语句显示窗口。 以上是PyQt5实现界面显示的基本步骤,具体实现过程中还需要根据实际需求进行相应的控件设置和布局操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值