在Qt中以高性能方式将(富)文本附加到QTextEdit或QTextBrowser中

Performantly appending (rich) text into QTextEdit or QTextBrowser in Qt

本文关键字:文本 QTextEdit QTextBrowser Qt 高性能 方式      更新时间:2023-10-16

QTextEdit可以简单地使用append()附加文本。但是,如果文档是富文本,则每次追加到文档时,显然都会重新分析它。这在Qt中似乎有点陷阱。

如果您将编辑框用作日志窗口,并且由于外部信号而快速连续追加文本,则追加可以轻松挂起您的应用,而不会显示任何中间追加,直到每个追加完成。

如何将富文本附加到 QTextEdit 而不会减慢整个 UI 的速度?

如果您希望每个追加项能够快速单独显示(而不是等到它们全部附加后再显示),则需要访问内部 QTextDocument:

void fastAppend(QString message,QTextEdit *editWidget)
{
    const bool atBottom = editWidget->verticalScrollBar()->value() == editWidget->verticalScrollBar()->maximum();
    QTextDocument* doc = editWidget->document();
    QTextCursor cursor(doc);
    cursor.movePosition(QTextCursor::End);
    cursor.beginEditBlock();
    cursor.insertBlock();
    cursor.insertHtml(message);
    cursor.endEditBlock();
    //scroll scrollarea to bottom if it was at bottom when we started
    //(we don't want to force scrolling to bottom if user is looking at a
    //higher position)
    if (atBottom) {
        scrollLogToBottom(editWidget);
    }
}
void scrollLogToBottom(QTextEdit *editWidget)
{
    QScrollBar* bar =  editWidget->verticalScrollBar();
    bar->setValue(bar->maximum());
}

滚动到底部是可选的,但在日志记录使用中,这是 UI 行为的合理默认值。

此外,如果您的应用同时执行许多其他处理,则将其附加到 fastAppend 的末尾,将优先实际尽快显示消息:

    //show the message in output right away by triggering event loop
    QCoreApplication::processEvents();

这实际上似乎是Qt中的一种陷阱。我知道为什么在QTextEdit中没有直接的fastAppend方法吗?或者这个解决方案有警告吗?

(我的公司实际上为这个建议向KDAB支付了费用,但这似乎很愚蠢,我认为这应该是更常识。