QT系列教程(11) TextEdit实现Qt 文本高亮

文本高亮

对于textedit里录入的部分单词我们可以实现高亮,实现高亮主要依赖于QSyntaxHighlighter。
我们先创建一个Qt Application类,类名MainWindow, 然后新增一个C++类,类名为MySyntaxHighlighter。

#ifndef MYSYNTAXHIGHLIGHTER_H
#define MYSYNTAXHIGHLIGHTER_H
#include <QSyntaxHighlighter>
#include <QTextDocument>
class MySyntaxHighlighter:public QSyntaxHighlighter
{Q_OBJECT
public:explicit MySyntaxHighlighter(QTextDocument* parent = 0);//重写实现高亮
protected:void highlightBlock(const QString& text);
};#endif // MYSYNTAXHIGHLIGHTER_H

这个类声明了highlightBlock函数,这是一个虚函数继承自QSyntaxHighlighter。每次我们录入文字时,会自动调用这个函数。下面实现MySyntaxHighlighter类

#include "mysyntaxhighlighter.h"
#include <QFont>MySyntaxHighlighter::MySyntaxHighlighter(QTextDocument* parent):QSyntaxHighlighter (parent)
{}void MySyntaxHighlighter::highlightBlock(const QString &text)
{QTextCharFormat myFormat;myFormat.setFont(QFont("微软雅黑"));myFormat.setFontWeight(QFont::Bold);myFormat.setForeground(Qt::green);//匹配charQString pattern = "\\bchar\\b";//创建正则表达式QRegExp express(pattern);//从索引0的位置开始匹配int index = text.indexOf(express);while (index>0) {int matchLen = express.matchedLength();//对匹配的字符串设置高亮setFormat(index, matchLen, myFormat);index = text.indexOf(express, index+matchLen);}
}

在highlightBlock函数中,我们实现了一个高亮的文字模式,当录入的字符串包含char时,char会被高亮。
我们在mainwindow.ui中添加一个textedit,然后在mainwindow的构造函数中添加我们刚才编写的高亮模块。

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);m_ligher = new MySyntaxHighlighter(ui->textEdit->document());
}

程序运行后,在编辑器中输入hello char,会看到char高亮了
https://cdn.llfc.club/1665137215851.jpg

实现代码编辑器

Qt 的案例中有提供过文本高亮和显示行号的demo,我把它整理起来了。
我们先声明codeeditor类,以及行号显示的类

#ifndef CODEEDITOR_H
#define CODEEDITOR_H#include <QPlainTextEdit>QT_BEGIN_NAMESPACE
class QPaintEvent;
class QResizeEvent;
class QSize;
class QWidget;
QT_END_NAMESPACEclass LineNumberArea;class CodeEditor : public QPlainTextEdit
{Q_OBJECTpublic:CodeEditor(QWidget *parent = nullptr);void lineNumberAreaPaintEvent(QPaintEvent *event);int lineNumberAreaWidth();protected:void resizeEvent(QResizeEvent *event) override;private slots:void updateLineNumberAreaWidth(int newBlockCount);void highlightCurrentLine();void updateLineNumberArea(const QRect &rect, int dy);private:QWidget *lineNumberArea;
};class LineNumberArea : public QWidget
{
public:LineNumberArea(CodeEditor *editor) : QWidget(editor), codeEditor(editor){}QSize sizeHint() const override{return QSize(codeEditor->lineNumberAreaWidth(), 0);}protected:void paintEvent(QPaintEvent *event) override{codeEditor->lineNumberAreaPaintEvent(event);}private:CodeEditor *codeEditor;
};#endif

具体代码类的实现

#include "codeeditor.h"#include <QPainter>
#include <QTextBlock>CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent)
{lineNumberArea = new LineNumberArea(this);connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth);connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea);connect(this, &CodeEditor::cursorPositionChanged, this, &CodeEditor::highlightCurrentLine);updateLineNumberAreaWidth(0);highlightCurrentLine();
}int CodeEditor::lineNumberAreaWidth()
{int digits = 1;int max = qMax(1, blockCount());while (max >= 10) {max /= 10;++digits;}int space = 3 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits;return space;
}void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
{setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
}void CodeEditor::updateLineNumberArea(const QRect &rect, int dy)
{if (dy)lineNumberArea->scroll(0, dy);elselineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());if (rect.contains(viewport()->rect()))updateLineNumberAreaWidth(0);
}void CodeEditor::resizeEvent(QResizeEvent *e)
{QPlainTextEdit::resizeEvent(e);QRect cr = contentsRect();lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
}void CodeEditor::highlightCurrentLine()
{QList<QTextEdit::ExtraSelection> extraSelections;if (!isReadOnly()) {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);
}void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
{QPainter painter(lineNumberArea);painter.fillRect(event->rect(), Qt::lightGray);QTextBlock block = firstVisibleBlock();int blockNumber = block.blockNumber();int top = qRound(blockBoundingGeometry(block).translated(contentOffset()).top());int bottom = top + qRound(blockBoundingRect(block).height());while (block.isValid() && top <= event->rect().bottom()) {if (block.isVisible() && bottom >= event->rect().top()) {QString number = QString::number(blockNumber + 1);painter.setPen(Qt::black);painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),Qt::AlignHCenter, number);}block = block.next();top = bottom;bottom = top + qRound(blockBoundingRect(block).height());++blockNumber;}
}

上面实现了代码编辑器的行号和当前行黄色高亮显示。
接下来实现高亮显示类

#ifndef HIGHLIGHTER_H
#define HIGHLIGHTER_H#include <QSyntaxHighlighter>
#include <QTextCharFormat>
#include <QRegularExpression>QT_BEGIN_NAMESPACE
class QTextDocument;
QT_END_NAMESPACE//! [0]
class Highlighter : public QSyntaxHighlighter
{Q_OBJECTpublic:Highlighter(QTextDocument *parent = 0);protected:void highlightBlock(const QString &text) override;private:struct HighlightingRule{QRegularExpression pattern;QTextCharFormat format;};QVector<HighlightingRule> highlightingRules;QRegularExpression commentStartExpression;QRegularExpression commentEndExpression;QTextCharFormat keywordFormat;QTextCharFormat classFormat;QTextCharFormat singleLineCommentFormat;QTextCharFormat multiLineCommentFormat;QTextCharFormat quotationFormat;QTextCharFormat functionFormat;
};
//! [0]#endif // HIGHLIGHTER_H

具体实现细节如下,先定义高亮的正则规则,然后在highlightBlock函数里根据规则点亮不同的单词

#include "highlighter.h"//! [0]
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);
//! [0] //! [1]}
//! [1]//! [2]classFormat.setFontWeight(QFont::Bold);classFormat.setForeground(Qt::darkMagenta);rule.pattern = QRegularExpression(QStringLiteral("\\bQ[A-Za-z]+\\b"));rule.format = classFormat;highlightingRules.append(rule);
//! [2]//! [3]singleLineCommentFormat.setForeground(Qt::red);rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*"));rule.format = singleLineCommentFormat;highlightingRules.append(rule);multiLineCommentFormat.setForeground(Qt::red);
//! [3]//! [4]quotationFormat.setForeground(Qt::darkGreen);rule.pattern = QRegularExpression(QStringLiteral("\".*\""));rule.format = quotationFormat;highlightingRules.append(rule);
//! [4]//! [5]functionFormat.setFontItalic(true);functionFormat.setForeground(Qt::blue);rule.pattern = QRegularExpression(QStringLiteral("\\b[A-Za-z0-9_]+(?=\\()"));rule.format = functionFormat;highlightingRules.append(rule);
//! [5]//! [6]commentStartExpression = QRegularExpression(QStringLiteral(" /\\*"));commentEndExpression = QRegularExpression(QStringLiteral("\\*/"));
}
//! [6]//! [7]
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);}}
//! [7] //! [8]setCurrentBlockState(0);
//! [8]//! [9]int startIndex = 0;if (previousBlockState() != 1)startIndex = text.indexOf(commentStartExpression);//! [9] //! [10]while (startIndex >= 0) {
//! [10] //! [11]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);}
}
//! [11]

接下来在MainWindow里添加editor

void MainWindow::setupEditor()
{QFont font;font.setFamily("Courier");font.setFixedPitch(true);font.setPointSize(10);editor = new CodeEditor();editor->setFont(font);highlighter = new Highlighter(editor->document());QFile file("mainwindow.h");if (file.open(QFile::ReadOnly | QFile::Text))editor->setPlainText(file.readAll());
}

运行程序后,输入部分代码显示如下
https://cdn.llfc.club/1665137935233.jpg
具体细节大家可以参考代码理解即可。

总结

源码链接https://gitee.com/secondtonone1/qt-learning-notes

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/855604.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

麻省理工IOT教授撰写的1058页Python程序设计人工智能实践手册!

为什么要学习Python&#xff1f; Python简单易学&#xff0c;且提供了丰富的第三方库&#xff0c;可以用较少的代码完成较多的工作&#xff0c;使开发者能够专注于如何解决问题而只花较少的时间去考虑如何编程。此外&#xff0c;Python还具有免费开源、跨平台、面向对象、胶水…

网络安全ctf比赛_学习资源整理,解题工具、比赛时间、解题思路、实战靶场、学习路线,推荐收藏!..._给一个照片,可以考虑的解题方向网络安全

对于想学习或者参加CTF比赛的朋友来说&#xff0c;CTF工具、练习靶场必不可少&#xff0c;今天给大家分享自己收藏的CTF资源&#xff0c;希望能对各位有所帮助。 CTF在线工具 首先给大家推荐我自己常用的3个CTF在线工具网站&#xff0c;内容齐全&#xff0c;收藏备用。 1、C…

!力扣105. 从前序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,20,7] 输出: [3,9,20,null,null,15,7] …

ARM架构简明教程

目录 一、ARM架构 1、RISC指令集 2、ARM架构数据类型的约定 2.1 ARM-v7架构数据类型的约定 2.2 ARM-v8架构数据类型的约定 3、CPU内部寄存器 4、特殊寄存器 4.1 SP寄存器 4.2 LR寄存器 4.3 PC寄存器 二、汇编 1、汇编指令&#xff08;常用&#xff09; 2、C函数的…

oracle数据库日常保养或巡检语句实践整理汇总

目录 1.目的 2.操作工具 3.实践说明 1.检查Oracle实例状态 2.检查Oracle在线日志状态 3.检查Oracle表空间状态 4.检查Oracle所有数据文件状态 5.检查Oracle数据库连接情况 6.检查Oracle表容量占用大小 7.检查Oracle备份 8.检查数据库表空间的使用情况 4.总结 1.目的 …

TSINGSEE青犀云边端技术如何助力视频监控实现高效管理与安全监控

随着信息技术的飞速发展&#xff0c;视频监控作为维护公共安全的重要手段&#xff0c;正逐渐融入人们的日常生活。在这个大数据、云计算、物联网等技术深度融合的时代&#xff0c;云边端技术作为一种新兴的技术架构&#xff0c;为视频监控带来了前所未有的变革与机遇。本文将以…

matlab 路面点云标线提取

目录 一、算法原理二、代码实现三、结果展示四、参考链接本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 算法来自本人自创。实现效果如下图所示,具体实现原理看代码即可。 二、代码实现 clc; cle…

办公楼导航系统:设计要点、功能实现与效益评估

随着现代办公楼的日益复杂化和规模化&#xff0c;如何高效、便捷地在楼宇内部进行定位和导航&#xff0c;已成为众多企业和员工关注的焦点。维小帮办公楼定位导航系统通过精准的定位和智能的导航功能&#xff0c;能够显著提升办公环境的智能化水平和办公效率。 一、维小帮办公…

k8s快速上手实操

前言 Kubernetes&#xff08;简称K8s&#xff09;是由Google开源的一个用于自动化部署、扩展和管理容器化应用程序的系统。自2014年发布以来&#xff0c;Kubernetes已经迅速成长为容器编排领域的标准&#xff0c;并在全球范围内得到了广泛的采用和认可。 Kubernetes作为现代容…

Mcgs屏幕脚本程序

目录 1.脚本程序概述1.1 脚本程序简介1.2 脚本程序编辑环境 2.脚本程序语言要素2.1 变量和常量2.2 对象2.3 事件2.4 表达式2.5 联行符2.6 运算符2.7 系统函数 3. 基本语句3.1 赋值语句3.2 条件语句3.3 循环语句3.4 跳出语句3.5 退出语句3.6 注释语句3.7 声明语句3.6 命名规则 1…

threejs视频融合 webgl

threejs三维视频融合 let objList []; const clock new THREE.Clock(); const container document.getElementById( container );const stats new Stats(); container.appendChild( stats.dom );const renderer new THREE.WebGLRenderer( { antialias: true } ); rendere…

Linux 防火墙 Firewall 和 Iptables 的使用

如果我们在Linux服务器的某个端口上运行了个服务&#xff0c;需要外网能访问到&#xff0c;就必须通过防火墙将服务运行端口给开启。Linux中有两种防火墙软件&#xff0c;CentOS7.0以上使用的是firewall&#xff0c;CentOS7.0以下使用的是iptables&#xff08;使用较少且不建议…

Jenkins+K8s实现持续集成(三)

接上面一篇JenkinsK8s实现持续集成&#xff08;二&#xff09;&#xff0c;K8s创建秘钥。 看secret kubectl get secret 删除secret kubectl delete secret hello-secret -n train 创建secret kubectl create secret docker-registry hello-secret --docker-server镜像仓库…

HarmonyOS【ArkUI组件--TextInput】

1.文本输入框基本用法 2. 使用文本输入框组件&#xff08;如何实现输入数字改变图片大小&#xff09; 在此博客的基础上继续编写&#xff1a;HarmonyOS【ArkUI组件--Text】-CSDN博客 ①代码如下&#xff1a; import font from ohos.font Entry Component struct Index {State …

开辟一个存储空间以存放一个结构体数据

在软件开发中&#xff0c;常常需要动态地分配和撤销内存空间&#xff0c;例如对动态链表中结点的插入与删除。在C语言中是利用库函数malloc和free来分配和撤销内存空间的。C提供了较简便而功能较强的运算符new和delete 来取代malloc和free函数。注意&#xff1a;new和delete是运…

白酒:酒文化传承中的挑战与机遇

随着时代的变迁&#xff0c;酒文化传承面临着许多挑战与机遇。我们来看看酒文化传承面临的挑战。随着现代生活方式的改变&#xff0c;人们对于传统酒文化的认知逐渐淡化。与此同时&#xff0c;年轻一代对于酒文化的兴趣不如老一辈浓厚&#xff0c;这使得酒文化的传承面临断层的…

每日复盘-202406018

今日关注&#xff1a; 20240617 20240618 六日涨幅最大: ------1--------300868--------- 杰美特 五日涨幅最大: ------1--------300868--------- 杰美特 四日涨幅最大: ------1--------300868--------- 杰美特 三日涨幅最大: ------1--------300462--------- 华铭智能 二日涨…

梅雨季机房运维注意事项

就在今天&#xff0c;江淮流域正式入梅啦。梅雨季雨水丰沛&#xff0c;机房运维要特别注意这些方面&#xff0c;以确保设备安全运行和数据中心的环境稳定。 首先&#xff0c;要防潮 具体措施 1、检查屋顶和墙壁密封性&#xff0c;确保机房屋顶和墙壁的密封性良好&#xff0c…

如何用 Google Chrome 浏览器浏览经过 XSLT 渲染的 XML 文件

对于经过XSLT渲染的XML文件&#xff0c;本来&#xff0c;可以直接用 IE (Internet Explorer) 打开&#xff0c;就能看到渲染之后的样子&#xff0c;很方便。但是后来&#xff0c;微软把 IE 换成了 Microsoft Edge&#xff0c;按理说这是比 IE 更先进的浏览器&#xff0c;可是偏…

ubuntu18.0.4安装gradio踩坑记

Collecting pandas (from gradio) Downloading http://mirrors.cloud.aliyuncs.com/pypi/packages/c3/e2/00cacecafbab071c787019f00ad84ca3185952f6bb9bca9550ed83870d4d/pandas-1.1.5-cp36-cp36m-manylinux1_x86_64.whl (9.5MB) 100% |████████████████…