2

I have a heavy QString.

I need to display it as an output.

I tried both QTextEdit or QTextBrowser. And all methods of setting text like setText, append, setPlainText.....The performance is really poor. The most annoying things is that setting thing on user interface meaning blocking the main thread. So the program will become unresponsive during the process.

Is there any better way to display visual text result?

tom
  • 1,302
  • 1
  • 16
  • 30

3 Answers3

3

At least if the document is rich text, every time you append to the document, it is apparently reparsed.

This is A LOT more performant: If you want each append to actually show quickly & separately (instead of waiting until they've all been appended before they are shown), you need to access the internal 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());
}

The scrolling to bottom is optional, but in logging use it's a reasonable default for UI behaviour.

This actually seems a kind of trap in Qt. I would know why there isn't a fastAppend method directly in QTextEdit? Or are there caveats to this solution?

(My company actually paid KDAB for this advice, but this seems so silly that I thought this should be more common knowledge.)

Original answer here.

savolai ᯓ
  • 666
  • 5
  • 20
1

Just got the same problem, and the resolution is very simple! Instead of creating a document + adding it immediately to the QTextBrowser/QTextEdit and then use cursor/set text to modify it, just postpone setting the document to the widget till AFTER you set the text / formatting... a complete life changer :)

rubmz
  • 1,947
  • 5
  • 27
  • 49
0

The best way would be to load text partially as background operation with thread that periodically emit signal to redraw GUI, or better: just use QTimer. Load first N lines, and then start QTimer that'll read more lines and append text inside widget. After reaching eof just kill that timer.

I believe that example can be helpful.

Konrad 'Zegis'
  • 15,101
  • 1
  • 16
  • 18