Qt实现文本编辑器光标高亮技术

在Qt中实现文本编辑器光标高亮技术可以通过多种方式实现,下面我将介绍几种常用的方法及其实现细节。

图片[1]_Qt实现文本编辑器光标高亮技术_知途无界

一、基础方法:使用QPlainTextEdit或QTextEdit

1. 继承QPlainTextEdit并重绘光标

class HighlightCursorTextEdit : public QPlainTextEdit {
    Q_OBJECT
public:
    explicit HighlightCursorTextEdit(QWidget *parent = nullptr)
        : QPlainTextEdit(parent) {
        // 设置光标宽度和颜色
        setCursorWidth(2);
        QPalette p = palette();
        p.setColor(QPalette::TextCursor, Qt::red); // 设置光标颜色
        setPalette(p);
    }

protected:
    void paintEvent(QPaintEvent *event) override {
        QPlainTextEdit::paintEvent(event);

        // 获取光标矩形
        QRect cursorRect = cursorRect(textCursor());

        // 绘制高亮光标
        QPainter painter(viewport());
        painter.setPen(QPen(Qt::red, 2));
        painter.drawLine(cursorRect.topLeft(), cursorRect.bottomLeft());
    }
};

2. 使用QTextCursor设置格式

// 设置光标所在行的背景色
void highlightCurrentLine() {
    QList<QTextEdit::ExtraSelection> extraSelections;

    QTextEdit::ExtraSelection selection;
    QColor lineColor = QColor(Qt::yellow).lighter(160);

    selection.format.setBackground(lineColor);
    selection.format.setProperty(QTextFormat::FullWidthSelection, true);
    selection.cursor = textCursor();
    selection.cursor.clearSelection();

    extraSelections.append(selection);

    setExtraSelections(extraSelections);
}

二、高级方法:自定义光标渲染

1. 使用QSyntaxHighlighter扩展

class CursorHighlighter : public QSyntaxHighlighter {
public:
    explicit CursorHighlighter(QTextDocument *parent = nullptr)
        : QSyntaxHighlighter(parent) {}

    void highlightBlock(const QString &text) override {
        // 获取文档光标位置
        QTextCursor cursor(document());

        // 如果当前块包含光标
        if (cursor.position() >= currentBlock().position() && 
            cursor.position() <= currentBlock().position() + currentBlock().length()) {

            QTextCharFormat format;
            format.setBackground(Qt::yellow);
            setFormat(0, text.length(), format);
        }
    }
};

2. 实现闪烁光标效果

class BlinkingCursorTextEdit : public QPlainTextEdit {
    Q_OBJECT
public:
    explicit BlinkingCursorTextEdit(QWidget *parent = nullptr)
        : QPlainTextEdit(parent), m_blinkTimer(new QTimer(this)) {

        connect(m_blinkTimer, &QTimer::timeout, this, &BlinkingCursorTextEdit::blinkCursor);
        m_blinkTimer->start(500); // 每500ms闪烁一次

        m_cursorVisible = true;
    }

protected:
    void paintEvent(QPaintEvent *event) override {
        QPlainTextEdit::paintEvent(event);

        if (m_cursorVisible && hasFocus()) {
            QRect cursorRect = cursorRect(textCursor());
            QPainter painter(viewport());
            painter.fillRect(cursorRect, Qt::red);
        }
    }

private slots:
    void blinkCursor() {
        m_cursorVisible = !m_cursorVisible;
        viewport()->update();
    }

private:
    QTimer *m_blinkTimer;
    bool m_cursorVisible;
};

三、完整实现方案

下面是一个完整的文本编辑器类,实现了光标高亮和当前行高亮:

class AdvancedTextEditor : public QPlainTextEdit {
    Q_OBJECT
public:
    explicit AdvancedTextEditor(QWidget *parent = nullptr)
        : QPlainTextEdit(parent) {

        // 初始化设置
        setLineWrapMode(QPlainTextEdit::NoWrap);
        setCursorWidth(2);

        // 高亮当前行
        connect(this, &QPlainTextEdit::cursorPositionChanged, 
                this, &AdvancedTextEditor::highlightCurrentLine);

        // 初始化闪烁定时器
        m_blinkTimer = new QTimer(this);
        connect(m_blinkTimer, &QTimer::timeout, this, &AdvancedTextEditor::blinkCursor);
        m_blinkTimer->start(500);

        // 初始高亮
        highlightCurrentLine();
    }

    void highlightCurrentLine() {
        QList<QTextEdit::ExtraSelection> extraSelections;

        if (!isReadOnly()) {
            QTextEdit::ExtraSelection selection;
            selection.format.setBackground(QColor(240, 240, 255));
            selection.format.setProperty(QTextFormat::FullWidthSelection, true);
            selection.cursor = textCursor();
            selection.cursor.clearSelection();
            extraSelections.append(selection);
        }

        setExtraSelections(extraSelections);
    }

protected:
    void paintEvent(QPaintEvent *event) override {
        QPlainTextEdit::paintEvent(event);

        // 绘制自定义光标
        if (m_cursorVisible && hasFocus()) {
            QTextCursor cursor = textCursor();
            QRect cursorRect = cursorRect(cursor);

            QPainter painter(viewport());
            QPen pen(Qt::red, 2);
            painter.setPen(pen);

            // 绘制竖线光标
            painter.drawLine(cursorRect.topLeft(), cursorRect.bottomLeft());

            // 如果是覆盖模式,绘制背景矩形
            if (overwriteMode() && cursor.position() < document()->characterCount() - 1) {
                cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
                QRect charRect = cursorRect(cursor);
                painter.fillRect(charRect, QColor(255, 0, 0, 50));
            }
        }
    }

    void focusInEvent(QFocusEvent *e) override {
        QPlainTextEdit::focusInEvent(e);
        m_cursorVisible = true;
        viewport()->update();
    }

    void focusOutEvent(QFocusEvent *e) override {
        QPlainTextEdit::focusOutEvent(e);
        m_cursorVisible = false;
        viewport()->update();
    }

private slots:
    void blinkCursor() {
        if (hasFocus()) {
            m_cursorVisible = !m_cursorVisible;
            viewport()->update();
        }
    }

private:
    QTimer *m_blinkTimer;
    bool m_cursorVisible = true;
};

四、性能优化建议

  1. 局部更新:只在光标位置变化时更新相关区域,而不是整个视口。
   void updateCursorRect() {
       QRect updateRect = cursorRect(textCursor()).adjusted(-2, -2, 2, 2);
       viewport()->update(updateRect);
   }
  1. 双缓冲技术:对于复杂的编辑器,启用双缓冲可以减少闪烁。
   setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
  1. 延迟渲染:对于大文档,可以使用QTextDocumentFragment进行分批渲染。

五、扩展功能

  1. 多光标支持
   void addSecondaryCursor(const QTextCursor &cursor) {
       QTextEdit::ExtraSelection extra;
       extra.cursor = cursor;
       extra.format.setBackground(QColor(200, 200, 255, 100));
       m_secondaryCursors.append(extra);
       updateExtraSelections();
   }
  1. 光标形状动画
   void animateCursor() {
       QPropertyAnimation *animation = new QPropertyAnimation(this, "cursorWidth");
       animation->setDuration(500);
       animation->setStartValue(1);
       animation->setEndValue(5);
       animation->setEasingCurve(QEasingCurve::InOutQuad);
       animation->start(QAbstractAnimation::DeleteWhenStopped);
   }
  1. 语法高亮光标
   void highlightSyntaxUnderCursor() {
       QTextCursor cursor = textCursor();
       cursor.select(QTextCursor::WordUnderCursor);
       QString word = cursor.selectedText();

       QTextCharFormat format;
       if (isKeyword(word)) {
           format.setBackground(Qt::yellow);
       }
       setExtraSelections({QTextEdit::ExtraSelection{cursor, format}});
   }

以上方法可以根据实际需求组合使用,在Qt中实现灵活多样的光标高亮效果。

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞55 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容