如何在QTextEdit中实现多行注释高亮显示?
QTextEdit多行注释高亮实现方案
问题分析
- HtmlHighlighter无效果原因:你提取的
HtmlHighlighter是专门针对**HTML注释()**设计的,而测试文本是C风格的/* */注释,两者匹配规则完全不同,因此应用后没有高亮效果。 - MyHtmlHighlighter仅支持单行注释原因:你的
MyHtmlHighlighter通过正则表达式/\*(.|\\n)*?\*/匹配注释,但QSyntaxHighlighter的highlightBlock方法是逐块(单行)处理文本的,正则表达式无法跨块匹配内容,导致跨行的/* */注释只能匹配到开头或结尾的单行部分。
解决方案:基于状态跟踪实现跨多行注释高亮
要实现跨多行的/* */注释高亮,需要利用QSyntaxHighlighter的状态机制:通过previousBlockState()获取上一行的状态,setCurrentBlockState()保存当前行的状态,以此跟踪是否处于注释块中。
修改后的MyHtmlHighlighter代码如下:
class MyHtmlHighlighter : public QSyntaxHighlighter { public: // 定义状态:正常状态、处于多行注释中 enum State { Normal = -1, InMultiLineComment }; MyHtmlHighlighter(QTextDocument* parent) : QSyntaxHighlighter(parent) { commentFormat.setForeground(QColor("#29ff3d")); commentFormat.setFontItalic(true); }; protected: void highlightBlock(const QString& text) override { // 获取上一行的状态,判断是否处于未结束的注释中 int currentState = previousBlockState(); if (currentState == -1) currentState = Normal; int pos = 0; int startPos = 0; while (pos < text.length()) { switch (currentState) { case Normal: // 寻找多行注释的起始标记 /* startPos = text.indexOf("/*", pos); if (startPos == -1) { // 没有找到注释起始,直接结束 pos = text.length(); } else { // 寻找当前行内的注释结束标记 */ int endPos = text.indexOf("*/", startPos + 2); if (endPos == -1) { // 当前行没有注释结束,高亮从起始到行尾,并标记状态为InMultiLineComment setFormat(startPos, text.length() - startPos, commentFormat); currentState = InMultiLineComment; pos = text.length(); } else { // 当前行内注释完整,高亮整个注释块 setFormat(startPos, endPos - startPos + 2, commentFormat); pos = endPos + 2; } } break; case InMultiLineComment: // 寻找注释结束标记 */ int endPos = text.indexOf("*/", pos); if (endPos == -1) { // 当前行没有注释结束,高亮整行 setFormat(pos, text.length() - pos, commentFormat); pos = text.length(); } else { // 找到注释结束,高亮从当前位置到结束标记,并恢复正常状态 setFormat(pos, endPos - pos + 2, commentFormat); currentState = Normal; pos = endPos + 2; } break; } } // 保存当前行的状态,供下一行使用 setCurrentBlockState(currentState); } private: QTextCharFormat commentFormat; };
使用说明
注意修改构造函数的参数,QSyntaxHighlighter的正确构造方式是传入QTextDocument*,而非QWidget*,初始化时代码调整为:
// 替换原来的初始化代码 MyHtmlHighlighter* highlighter_2 = new MyHtmlHighlighter(textEditList[1]->document());
修改后,无论是单行的/* */注释,还是跨多行的注释,都能正确高亮。
内容的提问来源于stack exchange,提问作者Cesar
相关产品推荐
相关产品推荐

