Qt官方示例:C++语法高亮器

您所在的位置:网站首页 苹果手机触屏失灵乱跳怎么办关机不了 Qt官方示例:C++语法高亮器

Qt官方示例:C++语法高亮器

#Qt官方示例:C++语法高亮器| 来源: 网络整理| 查看: 265

界面非常简单没啥可说的:

#include "mainwindow.h" #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setupFileMenu(); setupEditor(); setCentralWidget(editor); setWindowTitle(tr("语法高亮器")); } void MainWindow::newFile() { editor->clear(); } void MainWindow::openFile(const QString &path) { QString fileName = path; if (fileName.isNull()) fileName = QFileDialog::getOpenFileName(this, tr("打开文件"), "", "C++文件 (*.cpp *.h *.hpp)"); if (!fileName.isEmpty()) { QFile file(fileName); if (file.open(QFile::ReadOnly | QFile::Text)) editor->setPlainText(file.readAll()); } } void MainWindow::setupEditor() { QFont font; font.setFamily("Courier"); font.setFixedPitch(true); font.setPointSize(10); editor = new QTextEdit; editor->setFont(font); highlighter = new Highlighter(editor->document()); } void MainWindow::setupFileMenu() { QMenu *fileMenu = new QMenu(tr("&File"), this); menuBar()->addMenu(fileMenu); fileMenu->addAction(tr("&New"), QKeySequence::New,this, &MainWindow::newFile); fileMenu->addAction(tr("&Open..."), QKeySequence::Open,this, [this](){ openFile(); }); fileMenu->addAction(tr("E&xit"), QKeySequence::Quit,qApp, &QApplication::quit); }

主要来看看自定义语法高亮器的用法。

要实现自定义高亮规则需要继承 QSyntaxHighlighter 类并重新实现 highlightBlock()。

定义变量:

常用的变量:

格式设置为暗蓝色加粗:

在正则表达式里面,“\b”表示单词边界的断言,匹配的不一定是空格,只要是一个确定不是单词内容的字符即可匹配。如:

这里的-、=、+、:等符号不被认为是单词的内容即匹配上了。

又例如匹配成功:

匹配不成功:

类名:

暗洋红色加粗格式,匹配以Q为开头后面至少跟一个大小写字符的内容。

单行注释:

红色,匹配以“//”开头后面跟0个或多个不包含换行符的字符。

双引号引用的文本:

暗绿色,匹配前后为“"”,中间包含0个或多个任意字符的内容。

函数名: 

蓝色斜体,匹配以至少一个字母或数字或下划线开头且后面跟“(”的内容。这个规则是不严谨的,要是根据这个规则,下面这个错误的函数名也能匹配上:

不过问题不大,知道它的意思就行了。

多行注释:

“/\\*”中的“\\”表示转义字符“\”,实际上想表示的内容是:/\*。

“\”在正则表达式有表示将下一个字符标记为原意字符的意思(),“\*”表示:字符“*”。

即“/\\*”表示:字符串“/*”。同理“\\*/”表示:字符串“*/”。

实现的 highlightBlock() 函数: void Highlighter::highlightBlock(const QString &text) { for (const HighlightingRule &rule : qAsConst(highlightingRules)) { QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); while (matchIterator.hasNext()) { QRegularExpressionMatch match = matchIterator.next(); setFormat(match.capturedStart(), match.capturedLength(), rule.format); } } setCurrentBlockState(0); 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); } }

此函数在文档内容变化时会自动调用:

每次变化时传入的参数就是变化的文本块的文本:

高亮规则列表里的正则表达式挨个匹配,匹配上的就设置格式,这个没啥可说的,主要看一下多行注释的匹配。

Qt富文本的文本块(QTextBlock)提供了一个“状态”属性,即一个整数,默认为-1,可以通过设置文本块的状态来对文本块进行标记区分。

要处理可以跨越多个文本块的结构,需要知道上一个文本块的结束状态,使用previousBlockState() 函数可查询上一个文本块的结束状态。解析块后,可以使用 setCurrentBlockState() 设置当前文本块的状态。

在本例中,规定如果是要设置多行注释的文本块则状态值设为1。

如果上一个文本块中的文本不是多行注释的内容,则先查找当前文本是否有匹配 “/*” 的内容,indexOf() 如果查找到则返回匹配文本的索引位置,未找到则返回-1。

如果在当前文本块中找到 “/*”,则继续查找是否有 “*/”,如果没找到就认为 “*/” 在下面,当前文本属于多行注释中的内容即设置当前文本块状态为1。

这个类完整代码:

#include "highlighter.h" Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) { HighlightingRule rule; keywordFormat.setForeground(Qt::darkBlue); keywordFormat.setFontWeight(QFont::Bold); const QString keywordPatterns[] = { QStringLiteral("\\bchar\\b"), QStringLiteral("\\bclass\\b"), QStringLiteral("\\bconst\\b"), QStringLiteral("\\bdouble\\b"), QStringLiteral("\\benum\\b"), QStringLiteral("\\bexplicit\\b"), QStringLiteral("\\bfriend\\b"), QStringLiteral("\\binline\\b"), QStringLiteral("\\bint\\b"), QStringLiteral("\\blong\\b"), QStringLiteral("\\bnamespace\\b"), QStringLiteral("\\boperator\\b"), QStringLiteral("\\bprivate\\b"), QStringLiteral("\\bprotected\\b"), QStringLiteral("\\bpublic\\b"), QStringLiteral("\\bshort\\b"), QStringLiteral("\\bsignals\\b"), QStringLiteral("\\bsigned\\b"), QStringLiteral("\\bslots\\b"), QStringLiteral("\\bstatic\\b"), QStringLiteral("\\bstruct\\b"), QStringLiteral("\\btemplate\\b"), QStringLiteral("\\btypedef\\b"), QStringLiteral("\\btypename\\b"), QStringLiteral("\\bunion\\b"), QStringLiteral("\\bunsigned\\b"), QStringLiteral("\\bvirtual\\b"), QStringLiteral("\\bvoid\\b"), QStringLiteral("\\bvolatile\\b"), QStringLiteral("\\bbool\\b") }; for (const QString &pattern : keywordPatterns) { rule.pattern = QRegularExpression(pattern); rule.format = keywordFormat; highlightingRules.append(rule); } classFormat.setFontWeight(QFont::Bold); classFormat.setForeground(Qt::darkMagenta); rule.pattern = QRegularExpression(QStringLiteral("\\bQ[A-Za-z]+\\b")); rule.format = classFormat; highlightingRules.append(rule); singleLineCommentFormat.setForeground(Qt::red); rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*")); rule.format = singleLineCommentFormat; highlightingRules.append(rule); multiLineCommentFormat.setForeground(Qt::red); quotationFormat.setForeground(Qt::darkGreen); rule.pattern = QRegularExpression(QStringLiteral("\".*\"")); rule.format = quotationFormat; highlightingRules.append(rule); functionFormat.setFontItalic(true); functionFormat.setForeground(Qt::blue); rule.pattern = QRegularExpression(QStringLiteral("\\b[A-Za-z0-9_]+(?=\\()")); rule.format = functionFormat; highlightingRules.append(rule); commentStartExpression = QRegularExpression(QStringLiteral("/\\*")); commentEndExpression = QRegularExpression(QStringLiteral("\\*/")); } void Highlighter::highlightBlock(const QString &text) { for (const HighlightingRule &rule : qAsConst(highlightingRules)) { QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); while (matchIterator.hasNext()) { QRegularExpressionMatch match = matchIterator.next(); setFormat(match.capturedStart(), match.capturedLength(), rule.format); } } setCurrentBlockState(0); 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); } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3