当前位置: 首页 > article >正文

【Qt开发流程】之自定义语法高亮和使用HTML语法

描述

语法高亮(Syntax Highlighting)是一种在编辑器中突出显示代码语法元素的技术,使其更易于阅读和理解。
Qt提供了一个功能齐全的语法高亮框架,支持多种语言和格式,可以自定义颜色和样式。
对于使用Qt的开发人员来说,实现语法高亮是一个相对简单的过程。

HTML(HyperText Markup Language)是一种用于创建Web页面的标记语言,Qt也提供了一个用于显示HTML内容的类QTextBrowser。QTextBrowser类允许你将HTML内容显示在窗口中,并且支持基本的CSS样式。

相关的类包括QSyntaxHighlighter类QTextBrowser类

QSyntaxHighlighter类是用于实现语法高亮的类,可以通过继承该类并重新实现highlightBlock()函数来实现自定义语法高亮。该类也提供了一些常用的语法高亮规则,包括注释、字符串、数字、关键字等。

QSyntaxHighlighter类

QSyntaxHighlighter类允许定义语法高亮显示规则,此外还可以使用该类查询文档的当前格式或用户数据。
QSyntaxHighlighter类是实现QTextDocument语法荧光笔的基类。语法高亮器会自动高亮显示QTextDocument中的部分文本。当用户输入特定格式的文本(例如源代码)时,通常使用语法高亮显示,帮助用户阅读文本并识别语法错误。
要提供自己的语法高亮显示,必须创建QSyntaxHighlighter的子类并重新实现highlightBlock()
当创建QSyntaxHighlighter子类的实例时,将希望应用语法高亮的QTextDocument传递给它。例如:

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

在此之后,highlightBlock()函数将在必要时自动调用。使用highlightBlock()函数对传递给它的文本应用格式(例如设置字体和颜色)。QSyntaxHighlighter提供了setFormat()函数,该函数在当前文本块上应用给定的QTextCharFormat。例如:

  void MyHighlighter::highlightBlock(const QString &text)
  {
      QTextCharFormat myClassFormat;
      myClassFormat.setFontWeight(QFont::Bold);
      myClassFormat.setForeground(Qt::darkMagenta);

      QRegularExpression expression("\\bMy[A-Za-z]+\\b");
      QRegularExpressionMatchIterator i = expression.globalMatch(text);
      while (i.hasNext())
      {
        QRegularExpressionMatch match = i.next();
        setFormat(match.capturedStart(), match.capturedLength(), myClassFormat);
      }
  }

有些语法可以具有跨越多个文本块的结构。例如,c++语法高亮笔应该能够处理//多行注释。要处理这些情况,有必要知道前一个文本块的结束状态(例如:"in comment")。
highlightBlock()实现中,可以使用previousBlockState()函数查询前一个文本块的结束状态。解析完块后,可以使用setCurrentBlockState()保存最后一个状态。
currentBlockState()previousBlockState()函数返回一个int值。如果未设置状态,则返回值为-1。可以使用setCurrentBlockState()函数指定任何其他值来标识任何给定的状态。一旦状态被设置,QTextBlock将保持该值,直到它被再次设置或直到相应的文本段落被删除。
例如,如果你正在编写一个简单的c++语法高亮显示,你可以指定1来表示“in comment”:

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

  QRegularExpression startExpression("/\\*");
  QRegularExpression endExpression("\\*/");

  setCurrentBlockState(0);

  int startIndex = 0;
  if (previousBlockState() != 1)
      startIndex = text.indexOf(startExpression);

  while (startIndex >= 0) {
     QRegularExpressionMatch endMatch;
     int endIndex = text.indexOf(endExpression, startIndex, &endMatch);
     int commentLength;
     if (endIndex == -1) {
         setCurrentBlockState(1);
         commentLength = text.length() - startIndex;
     } else {
         commentLength = endIndex - startIndex
                         + endMatch.capturedLength();
     }
     setFormat(startIndex, commentLength, multiLineCommentFormat);
     startIndex = text.indexOf(startExpression,
                               startIndex + commentLength);
  }

在上面的例子中,我们首先将当前块状态设置为0。然后,如果前一个块以注释结束,则从当前块的开头突出显示(startIndex = 0),否则,搜索给定的开始表达式。如果在文本块中找不到指定的结束表达式,我们通过调用setCurrentBlockState()来改变当前块状态,并确保块的其余部分突出显示。
此外,您可以分别使用format()和currentBlockUserData()函数查询当前格式化和用户数据。您还可以使用setCurrentBlockUserData()函数将用户数据附加到当前文本块。QTextBlockUserData可用于存储自定义设置。在语法高亮的情况下,它特别有趣,因为它可以缓存您在解析段落文本时发现的信息。例如,请参阅setCurrentBlockUserData()文档。

void QSyntaxHighlighter::setCurrentBlockUserData(QTextBlockUserData *data):

将给定的数据附加到当前文本块。所有权传递给底层文本文档,即提供的QTextBlockUserData对象将被删除,如果相应的文本块被删除。
QTextBlockUserData可用于存储自定义设置。在语法高亮的情况下,它特别有趣,因为它可以缓存您在解析段落文本时发现的信息。
例如,在解析文本时,您可以跟踪您遇到的括号字符('{[('之类的)),并将它们的相对位置和实际的QChar存储在从QTextBlockUserData派生的简单类中:

  struct ParenthesisInfo
  {
      QChar char;
      int position;
  };

  struct BlockData : public QTextBlockUserData
  {
      QVector<ParenthesisInfo> parentheses;
  };

在关联编辑器中的光标导航期间,您可以询问当前QTextBlock(使用QTextCursor::block()函数检索)是否具有用户数据对象集,并将其强制转换为BlockData对象。然后,您可以检查当前光标位置是否与先前记录的圆括号位置匹配,并根据圆括号的类型(开始或结束)查找同一级别上的下一个开始或结束圆括号。
通过这种方式,您可以进行可视化的括号匹配,并从当前光标位置突出显示到匹配的括号。这使得在编辑括号密集的代码时,更容易发现代码中缺少的括号,并找到相应的开/闭括号。

QSyntaxHighlighter示例

下面是一个简单的示例,演示如何使用QSyntaxHighlighter来实现C++代码的语法高亮。

#include <QSyntaxHighlighter>
#include <QTextCharFormat>
#include <QRegularExpression>
class CppHighlighter : public QSyntaxHighlighter
{
public:
    CppHighlighter(QTextDocument* parent = nullptr) : QSyntaxHighlighter(parent)
    {
        HighlightRule rule;

        rule.pattern = QRegularExpression("//[^\n]*");
        rule.format.setForeground(Qt::darkGreen);
        m_rules.append(rule);

        rule.pattern = QRegularExpression("\"[^\"]*\"");
        rule.format.setForeground(Qt::red);
        m_rules.append(rule);

        rule.pattern = QRegularExpression("\\b[0-9]+\\b");
        rule.format.setForeground(Qt::blue);
        m_rules.append(rule);

        rule.pattern = QRegularExpression("\\b(void|int|float|double|char|bool)\\b");
        rule.format.setForeground(Qt::darkMagenta);
        m_rules.append(rule);
    }

protected:
    void highlightBlock(const QString& text) override
    {
        for (const HighlightRule& rule : m_rules) {
            QRegularExpressionMatchIterator it = rule.pattern.globalMatch(text);
            while (it.hasNext()) {
                QRegularExpressionMatch match = it.next();
                setFormat(match.capturedStart(), match.capturedLength(), rule.format);
            }
        }
    }

private:
    struct HighlightRule
    {
        QRegularExpression pattern;
        QTextCharFormat format;
    };

    QVector<HighlightRule> m_rules;
};

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

    QPlainTextEdit editor;
    CppHighlighter highlighter(editor.document());
    editor.show();

    return app.exec();
}
  • 结果

在这里插入图片描述

HTML

QTextBrowser类是一个用于显示HTML内容的控件,具有基本的浏览器功能,如链接、样式、图像等。该控件支持标准的HTML 4.0语法和基本的CSS样式。

示例:

#include <QApplication>
#include <QTextBrowser>

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

    QTextBrowser browser;
    browser.setHtml("<h1>Hello World!</h1>");
    browser.show();

    return app.exec();
}

在这里插入图片描述

结论

人生就像一杯水,孤独,孤独,孤独,一辈子就完了


http://www.kler.cn/news/155979.html

相关文章:

  • Proteus仿真--基于ADC0832设计的两路电压表
  • Mongodb安装及其使用
  • Linux 基本语句_14_信号灯实验
  • Hdoop学习笔记(HDP)-Part.06 安装OracleJDK
  • 【Java基础系列】BigDecimal入门
  • GB/T 37380-2019抗污易洁涂膜玻璃检测
  • Paxos 算法
  • 算法通关村第十六关-白银挑战滑动窗口经典题目
  • 第十七章 其他-rpc、rabbitmq(如何对消息做持久化、如何控制消息被消费的顺序)、celery(应用场景、运行机制、如何实现定时任务)
  • postgres在docker中使用
  • LeetCode刷题---反转链表
  • SCAU:链表创建与插入结点(填空)
  • word表格图片批处理参考程序
  • Linux-usb触摸板去除鼠标箭头
  • Ubuntu20.24 安装ecCodes,包括 tar.gz 和 python(笔记)
  • [网络安全]dos命令
  • Sakila数据库和World数据库
  • Vue+ElementUI+C#前后端分离:监控长耗时任务的实践
  • [足式机器人]Part4 南科大高等机器人控制课 Ch00 课程简介
  • C语言,求取数组的序亏:已知一个整数数组,求出个数组中每个元素在整个 数组的排序。
  • 鸿蒙(HarmonyOS)应用开发——构建页面(题目答案)
  • 93. 复原 IP 地址
  • 华为手环配置技巧
  • Java 中 IO 流分为几种?
  • 【算法思考记录】力扣1423. 可获得的最大点数[Python3, 滑动窗口]
  • golang 实现单向链表(lru)、双向链表、双向循环链表
  • Error:cannot launch node of type [map_server/map_server]
  • A++ 敏捷开发-1 如何改善
  • 常微分方程组的数值解法(C++)
  • WPS开发文档