Qt编程:QSyntaxHighlighter使用

QSyntaxHighlighter 是 Qt 框架中的一个类,用于实现语法高亮功能。它允许开发者为文本编辑器或类似组件中的特定文本模式(如编程语言代码)添加颜色和格式高亮。

基本概念

QSyntaxHighlighter 是一个抽象基类,需要子类化来实现具体的语法高亮规则。它通常与 QTextEdit 或 QPlainTextEdit 一起使用,为这些文本编辑组件提供语法高亮功能。

主要功能

  1. 根据预定义的规则自动高亮文本

  2. 在文本更改时动态更新高亮

  3. 支持多种格式组合(颜色、字体、背景等)

  4. 可扩展性强,可以处理各种语言的语法

使用方法

基本步骤

  1. 子类化 QSyntaxHighlighter

  2. 实现 highlightBlock(const QString &text) 方法

  3. 定义高亮规则

  4. 将高亮器附加到文本编辑器

示例代码

#include 
#include 
#include 

class MyHighlighter : public QSyntaxHighlighter
{
    Q_OBJECT

public:
    MyHighlighter(QTextDocument *parent = nullptr);

protected:
    void highlightBlock(const QString &text) override;

private:
    struct HighlightingRule
    {
        QRegularExpression pattern;
        QTextCharFormat format;
    };
    QVector highlightingRules;

    QTextCharFormat keywordFormat;
    QTextCharFormat singleLineCommentFormat;
    // 其他格式...
};

MyHighlighter::MyHighlighter(QTextDocument *parent)
    : QSyntaxHighlighter(parent)
{
    // 设置关键字格式
    keywordFormat.setForeground(Qt::darkBlue);
    keywordFormat.setFontWeight(QFont::Bold);
    
    // 定义关键字
    QStringList keywords;
    keywords << "if" << "else" << "for" << "while" << "return";
    
    // 添加关键字规则
    for (const QString &keyword : keywords) {
        HighlightingRule rule;
        rule.pattern = QRegularExpression("\\b" + keyword + "\\b");
        rule.format = keywordFormat;
        highlightingRules.append(rule);
    }
    
    // 设置单行注释格式
    singleLineCommentFormat.setForeground(Qt::gray);
    HighlightingRule commentRule;
    commentRule.pattern = QRegularExpression("//[^\n]*");
    commentRule.format = singleLineCommentFormat;
    highlightingRules.append(commentRule);
}

void MyHighlighter::highlightBlock(const QString &text)
{
    // 应用所有规则
    for (const HighlightingRule &rule : highlightingRules) {
        QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
        while (matchIterator.hasNext()) {
            QRegularExpressionMatch match = matchIterator.next();
            setFormat(match.capturedStart(), match.capturedLength(), rule.format);
        }
    }
    
    // 处理多行状态(如多行注释)
    setCurrentBlockState(0); // 重置状态
}

高级特性

多行高亮

对于跨越多行的语法元素(如多行注释),可以使用块状态:

// 在构造函数中添加多行注释规则
multiLineCommentFormat.setForeground(Qt::gray);
commentStartExpression = QRegularExpression("/\\*");
commentEndExpression = QRegularExpression("\\*/");

// 修改highlightBlock
void MyHighlighter::highlightBlock(const QString &text)
{
    // ...其他规则处理
    
    // 多行注释处理
    int startIndex = 0;
    if (previousBlockState() != 1)
        startIndex = text.indexOf(commentStartExpression);

    while (startIndex >= 0) {
        QRegularExpressionMatch match = commentEndExpression.match(text, startIndex);
        int endIndex = match.capturedStart();
        int commentLength = 0;
        if (endIndex == -1) {
            setCurrentBlockState(1);
            commentLength = text.length() - startIndex;
        } else {
            commentLength = endIndex - startIndex + match.capturedLength();
        }
        setFormat(startIndex, commentLength, multiLineCommentFormat);
        startIndex = text.indexOf(commentStartExpression, startIndex + commentLength);
    }
}

动态更新

当文档内容改变时,QSyntaxHighlighter 会自动重新高亮受影响的文本部分。

性能优化

对于大型文档,可以考虑以下优化:

  1. 使用更高效的正则表达式

  2. 限制高亮范围

  3. 缓存格式信息

实际应用

集成到文本编辑器

QPlainTextEdit *editor = new QPlainTextEdit;
MyHighlighter *highlighter = new MyHighlighter(editor->document());

基础语法高亮效果

代码示例(C++ 高亮)
// 示例:高亮C++关键字、注释和字符串
void CppHighlighter::highlightBlock(const QString &text) {
    // 高亮关键字(蓝色加粗)
    QTextCharFormat keywordFormat;
    keywordFormat.setForeground(Qt::darkBlue);
    keywordFormat.setFontWeight(QFont::Bold);

    QStringList keywords = {"if", "else", "for", "while", "return", "class", "void"};

    for (const QString &keyword : keywords) {
        QRegularExpression regex("\\b" + keyword + "\\b");
        QRegularExpressionMatchIterator it = regex.globalMatch(text);
        while (it.hasNext()) {
            QRegularExpressionMatch match = it.next();
            setFormat(match.capturedStart(), match.capturedLength(), keywordFormat);
        }
    }

    // 高亮单行注释(灰色)
    QTextCharFormat commentFormat;
    commentFormat.setForeground(Qt::gray);
    QRegularExpression commentRegex("//[^\n]*");
    QRegularExpressionMatchIterator commentIt = commentRegex.globalMatch(text);
    while (commentIt.hasNext()) {
        QRegularExpressionMatch match = commentIt.next();
        setFormat(match.capturedStart(), match.capturedLength(), commentFormat);
    }

    // 高亮字符串(绿色)
    QTextCharFormat stringFormat;
    stringFormat.setForeground(Qt::darkGreen);
    QRegularExpression stringRegex("\"[^\"]*\"");
    QRegularExpressionMatchIterator stringIt = stringRegex.globalMatch(text);
    while (stringIt.hasNext()) {
        QRegularExpressionMatch match = stringIt.next();
        setFormat(match.capturedStart(), match.capturedLength(), stringFormat);
    }
}
效果展示
#include   // 这是注释

int main() {
    if (true) {  // 关键字高亮
        std::cout << "Hello, World!";  // 字符串高亮
    }
    return 0;  // 关键字高亮
}

呈现效果

  • ifreturn 等关键字显示为 蓝色加粗

  • // 这是注释 显示为 灰色

  • "Hello, World!" 字符串显示为 绿色

多行注释高亮

代码示例
// 处理多行注释(如 /* ... */)
void CppHighlighter::highlightBlock(const QString &text) {
    // ...(其他规则)

    // 多行注释高亮
    QTextCharFormat multiLineCommentFormat;
    multiLineCommentFormat.setForeground(Qt::gray);

    int startIndex = 0;
    if (previousBlockState() != 1) {
        startIndex = text.indexOf("/*");
    }

    while (startIndex >= 0) {
        int endIndex = text.indexOf("*/", startIndex);
        if (endIndex == -1) {
            setCurrentBlockState(1);  // 表示注释未结束
            setFormat(startIndex, text.length() - startIndex, multiLineCommentFormat);
            break;
        } else {
            int commentLength = endIndex - startIndex + 2;
            setFormat(startIndex, commentLength, multiLineCommentFormat);
            startIndex = text.indexOf("/*", endIndex);
        }
    }
}
效果展示
/* 这是一个
   多行注释 */
int main() {
    return 0;
}

呈现效果

  • /* 这是一个 ... */ 整个多行注释显示为 灰色,即使跨越多行也能正确高亮。

数字高亮

代码示例
// 高亮数字(红色)
void CppHighlighter::highlightBlock(const QString &text) {
    // ...(其他规则)

    QTextCharFormat numberFormat;
    numberFormat.setForeground(Qt::red);

    QRegularExpression numberRegex("\\b\\d+\\b");
    QRegularExpressionMatchIterator numberIt = numberRegex.globalMatch(text);
    while (numberIt.hasNext()) {
        QRegularExpressionMatch match = numberIt.next();
        setFormat(match.capturedStart(), match.capturedLength(), numberFormat);
    }
}
效果展示
int x = 42;  // 数字高亮
float pi = 3.14;

呈现效果

  • 42 和 3.14 显示为 红色

自定义高亮规则(如 Python 高亮)

代码示例
# Python 语法高亮
def python_highlighter(text):
    # 高亮关键字(橙色)
    keywords = ["def", "if", "else", "for", "while", "return"]
    for keyword in keywords:
        if keyword in text:
            apply_highlight(keyword, ORANGE)

    # 高亮字符串(绿色)
    if "\"" in text or "'" in text:
        apply_highlight(string, GREEN)

    # 高亮注释(灰色)
    if text.strip().startswith("#"):
        apply_highlight(comment, GRAY)
效果展示
def greet(name):  # 关键字高亮
    print(f"Hello, {name}!")  # 字符串高亮

呈现效果

  • def 显示为 橙色

  • "Hello, {name}!" 显示为 绿色

  • # 关键字高亮 显示为 灰色

 在 Qt 中使用 QSyntaxHighlighter

完整示例
// main.cpp
#include 
#include 
#include "cpphighlighter.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QPlainTextEdit editor;
    editor.setWindowTitle("C++ 语法高亮编辑器");
    editor.resize(600, 400);

    // 应用高亮器
    CppHighlighter highlighter(editor.document());

    editor.show();
    return app.exec();
}

运行效果

  • 编辑器会自动高亮 C++ 代码的关键字、注释、字符串和数字。

总结

功能 实现方式 效果示例
关键字高亮 正则匹配 \bif\b if → 蓝色加粗
注释高亮 匹配 // 或 /* ... */ // comment → 灰色
字符串高亮 匹配 "..." 或 '...' "text" → 绿色
数字高亮 匹配 \d+ 123 → 红色
多行高亮 使用 setCurrentBlockState() /* ... \n ... */ → 完整高亮

支持不同语言

可以通过切换不同的高亮器或在高亮器内部切换规则集来实现多语言支持。

注意事项

  1. 正则表达式性能会影响高亮效率

  2. 复杂的语法可能需要更精细的状态管理

  3. 某些特殊语法结构可能需要自定义解析

QSyntaxHighlighter 提供了强大的语法高亮基础,通过合理的规则设计和状态管理,可以实现各种编程语言和标记语言的语法高亮功能,提升代码编辑体验。它的主要优势在于与 Qt 文本编辑组件的无缝集成和相对简单的实现方式。

你可能感兴趣的:(QT开发,qt,高亮显示)