我正在使用Qt的QSyntaxHighlighter在QML TextEdit中为某些类似于C的语法着色

除多行注释外,其他所有内容都很好。

我以这种方式检测到它们:

void highlightBlock(QString const& text) override {
    bool inMultilineComment = previousBlockState() == STATES::COMMENT;
    bool inSingleLineComment = false;
    int previousIndex = 0;

    QRegularExpression expr("(\\/\\*|\\*\\/|\\/\\/|\n)"); // will match either /**, /**, // or \n
    QRegularExpressionMatchIterator it = expr.globalMatch(text);

    while(it.hasNext()) {
        QRegularExpressionMatch match = it.next();

        const QString captured = match.captured(1);

        if(captured == "/*" && !inSingleLineComment) {
            inMultilineComment = true;
            previousIndex = match.capturedStart(1);
        }

        if(captured == "*/" && inMultilineComment) {
            inMultilineComment = false;
            setFormat(previousIndex, match.capturedEnd(1) - previousIndex, _commentFormat);
        }

        if(captured == "//" && !inMultilineComment) {
            inSingleLineComment = true;
        }

        if(captured == "\n" && inSingleLineComment) {
            inSingleLineComment = false;
        }
    }

    if(inMultilineComment) {
        setFormat(previousIndex, text.size() - previousIndex, _commentFormat);
        setCurrentBlockState(STATES::COMMENT);
    }
    else {
        setCurrentBlockState(STATES::NONE);
    }
}

直到我接受已经上色的多行注释,并且一开始删除/*时,它才起作用。仅对包含/*的块进行处理并重新上色,而不会对随后的块进行重新着色,这意味着它们在未显示时会继续显示为注释。

是否有一种简单的方法告诉QSyntaxHighlighter重新处理以下块以防止出现此类色差?

最佳答案

我最近遇到了同样的问题,并发现Qt实际上应该为您处理此问题,前提是您正确设置了blockState。

如果您查看Qt5源代码中的QSyntaxHighlighterPrivate::reformatBlocks的sourceCode,您将看到

while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) {
    const int stateBeforeHighlight = block.userState();
    reformatBlock(block);
    forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight);
    block = block.next();
}

https://code.woboq.org/qt5/qtbase/src/gui/text/qsyntaxhighlighter.cpp.html#165检索

该代码(由高亮显示的QTextDocument中的contentChange信号触发)将从刚修改的块开始遍历每个块(行)。假设基于刚刚发生的类型更改来更改块的状态,它将继续处理以下块。这意味着您需要为每行正确设置userState,而Qt应该处理其余部分。

给出例子
    /*
     * This is a comment
     *
     * That I made
     */

您可能希望在每行都设置了STATES::COMMENT的情况下开始,但最后一行应设置为STATES::NONE。完成删除初始/*的操作后,需要确保将块状态重置为STATES::NONE。这将触发Qt重新运行下一个块,这也将需要更改其状态,等等。

在我的(python)代码中,我最终使用了打印语句和实际调试的组合来跟踪状态更改的传播,并弄清了错误更新的位置和中断的更新链。您的代码从表面上看是正确的,尽管我没有尝试编译和运行它,但是我怀疑在某些情况下会触发某些情况,即在编辑后状态未正确更新。

关于c++ - QSyntaxHighlighter和多行注释,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51012969/

10-12 23:17