Qt给QPlainTextEdit设置行号

[复制链接]
发表于 2025-11-6 20:16:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
linenumberarea.h
  1. #ifndef LINENUMBERAREA_H
  2. #define LINENUMBERAREA_H
  3. #include <QWidget>
  4. #include <QPainter>
  5. #include <QTextBlock>
  6. #include <QPlainTextEdit>
  7. class LineNumberArea;
  8. class CodeEditor : public QPlainTextEdit
  9. {
  10.     Q_OBJECT
  11. public:
  12.     CodeEditor(QWidget *parent = nullptr);
  13.     //自定义的绘制事件处理函数,专门用于在行号区域绘制行号
  14.     void lineNumberAreaPaintEvent(QPaintEvent *event);
  15.     //负责计算并返回行号区域的宽度。这个函数通常在文本编辑器中使用,
  16.     //以确保行号区域的宽度能够容纳所有可能的行号。
  17.     int lineNumberAreaWidth();
  18. protected:
  19.     //用于处理窗口或控件的大小调整事件
  20.     //该方法确保在编辑器的大小变化时,行号区域能够正确调整其大小和位置。
  21.     void resizeEvent(QResizeEvent *event) override;
  22. private slots:
  23.     //,负责更新行号区域的宽度。这个函数在文本块数量变化时调用,
  24.     //以确保行号区域的宽度足够显示所有行号。
  25.     void updateLineNumberAreaWidth(int newBlockCount);
  26.     //高亮当前行
  27.     void highlightCurrentLine();
  28.     //更新行号区域
  29.     void updateLineNumberArea(const QRect &rect, int dy);
  30. private:
  31.     QWidget *lineNumberArea;
  32. };
  33. class LineNumberArea : public QWidget
  34. {
  35. public:
  36.     LineNumberArea(CodeEditor *editor) : QWidget(editor),
  37.         codeEditor(editor){}
  38.     //该方法计算并返回行号区域的建议大小
  39.     QSize sizeHint() const override
  40.     {
  41.         return QSize(codeEditor->lineNumberAreaWidth(), 0);
  42.     }
  43. protected:
  44.     //该方法负责在行号区域绘制行号
  45.     void paintEvent(QPaintEvent *event) override
  46.     {
  47.         codeEditor->lineNumberAreaPaintEvent(event);
  48.     }
  49. private:
  50.     CodeEditor *codeEditor;
  51. };
  52. #endif // LINENUMBERAREA_H
复制代码
linenumberarea.cpp
  1. #include "linenumberarea.h"
  2. CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent)
  3. {
  4.     lineNumberArea = new LineNumberArea(this);
  5.     connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth);
  6.     connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea);
  7.     connect(this, &CodeEditor::cursorPositionChanged, this, &CodeEditor::highlightCurrentLine);
  8.     updateLineNumberAreaWidth(0);//计算行号区域宽度
  9.     highlightCurrentLine();//高亮显示
  10. }
  11. int CodeEditor::lineNumberAreaWidth()
  12. {
  13.     int digits = 1;
  14.     int max = qMax(1, blockCount());
  15.     //计算数位
  16.     while (max >= 10) {
  17.         max /= 10;
  18.         ++digits;
  19.     }
  20.     //取字符9的宽度
  21.     int space = 3 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits;
  22.     return space;
  23. }
  24. void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
  25. {
  26.     setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
  27. }
  28. void CodeEditor::updateLineNumberArea(const QRect &rect, int dy)
  29. {
  30.     if (dy)
  31.         lineNumberArea->scroll(0, dy);
  32.     else
  33.         lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());
  34.     if (rect.contains(viewport()->rect()))
  35.         updateLineNumberAreaWidth(0);
  36. }
  37. void CodeEditor::resizeEvent(QResizeEvent *e)
  38. {
  39.     QPlainTextEdit::resizeEvent(e);
  40.     QRect cr = contentsRect();
  41.     lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
  42. }
  43. void CodeEditor::highlightCurrentLine()
  44. {
  45.     QList<QTextEdit::ExtraSelection> extraSelections;
  46.     if (!isReadOnly()) {
  47.         QTextEdit::ExtraSelection selection;
  48.         QColor lineColor = QColor(Qt::yellow).lighter(160);
  49.         selection.format.setBackground(lineColor);
  50.         selection.format.setProperty(QTextFormat::FullWidthSelection, true);
  51.         selection.cursor = textCursor();
  52.         selection.cursor.clearSelection();
  53.         extraSelections.append(selection);
  54.     }
  55.     setExtraSelections(extraSelections);
  56. }
  57. void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
  58. {
  59.     QPainter painter(lineNumberArea);
  60.     painter.fillRect(event->rect(), Qt::lightGray);
  61.     QTextBlock block = firstVisibleBlock();
  62.     int blockNumber = block.blockNumber();
  63.     int top = qRound(blockBoundingGeometry(block).translated(contentOffset()).top());
  64.     int bottom = top + qRound(blockBoundingRect(block).height());
  65.     while (block.isValid() && top <= event->rect().bottom()) {
  66.         if (block.isVisible() && bottom >= event->rect().top()) {
  67.             QString number = QString::number(blockNumber + 1);
  68.             painter.setPen(Qt::black);
  69.             painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
  70.                              Qt::AlignRight, number);
  71.         }
  72.         block = block.next();
  73.         top = bottom;
  74.         bottom = top + qRound(blockBoundingRect(block).height());
  75.         ++blockNumber;
  76.     }
  77. }
复制代码
mainwindow.h
  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QMainWindow>
  4. QT_BEGIN_NAMESPACE
  5. namespace Ui { class MainWindow; }
  6. QT_END_NAMESPACE
  7. class MainWindow : public QMainWindow
  8. {
  9.     Q_OBJECT
  10. public:
  11.     MainWindow(QWidget *parent = nullptr);
  12.     ~MainWindow();
  13. private:
  14.     Ui::MainWindow *ui;
  15. };
  16. #endif // MAINWINDOW_H
复制代码
mainwindow.cpp
  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include "linenumberarea.h"
  4. #include <QDebug>
  5. MainWindow::MainWindow(QWidget *parent)
  6.     : QMainWindow(parent)
  7.     , ui(new Ui::MainWindow)
  8. {
  9.     ui->setupUi(this);
  10.     CodeEditor *aaa=new CodeEditor();
  11.     setCentralWidget(aaa);
  12.     aaa->setPlainText("1234567891011");
  13.     qDebug()<<aaa->toPlainText();
  14. }
  15. MainWindow::~MainWindow()
  16. {
  17.     delete ui;
  18. }
复制代码
main.cpp
  1. #include "mainwindow.h"
  2. #include <QApplication>
  3. int main(int argc, char *argv[])
  4. {
  5.     QApplication a(argc, argv);
  6.     MainWindow w;
  7.     w.show();
  8.     return a.exec();
  9. }
复制代码
运行截图:


回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表