How to append text to QPlainTextEdit without adding newline, and keep scroll at the bottom?

后端 未结 4 1269
时光取名叫无心
时光取名叫无心 2020-11-29 05:15

I need to append text to QPlainTextEdit without adding a newline to the text, but both methods appendPlainText() and appendHtml() adds

相关标签:
4条回答
  • 2020-11-29 05:34

    The current Answer was not an option for me. It was much simplier to add html with no new lines with the following method.

    //logs is a QPlainTextEdit object
    ui.logs->moveCursor(QTextCursor::End);
    ui.logs->textCursor().insertHtml(out);
    ui.logs->moveCursor(QTextCursor::End);
    
    0 讨论(0)
  • 2020-11-29 05:39

    Ok, I'm not sure if my solution is actually "nice", but it seems to work for me: I just made new class QPlainTextEdit_My inherited from QPlainTextEdit, and added new methods appendPlainTextNoNL(), appendHtmlNoNL(), insertNL().

    Please NOTE: read comments about params check_nl and check_br carefully, this is important! I spent several hours to figure out why is my widget so slow when I append text without new paragraphs.

    /******************************************************************************************
     * INCLUDED FILES
     *****************************************************************************************/
    
    #include "qplaintextedit_my.h"
    #include <QScrollBar>
    #include <QTextCursor>
    #include <QStringList>
    #include <QRegExp>
    
    
    /******************************************************************************************
     * CONSTRUCTOR, DESTRUCTOR
     *****************************************************************************************/
    
    QPlainTextEdit_My::QPlainTextEdit_My(QWidget *parent) :
       QPlainTextEdit(parent)
    {
    
    }
    
    QPlainTextEdit_My::QPlainTextEdit_My(const QString &text, QWidget *parent) :
       QPlainTextEdit(text, parent)
    {
    
    }        
    
    /******************************************************************************************
     * METHODS
     *****************************************************************************************/
    
    /* private      */
    
    /* protected    */
    
    /* public       */
    
    /**
     * append html without adding new line (new paragraph)
     *
     * @param html       html text to append
     * @param check_nl   if true, then text will be splitted by \n char,
     *                   and each substring will be added as separate QTextBlock.
     *                   NOTE: this important: if you set this to false,
     *                   then you should append new blocks manually (say, by calling appendNL() )
     *                   because one huge block will significantly slow down your widget.
     */
    void QPlainTextEdit_My::appendPlainTextNoNL(const QString &text, bool check_nl)
    {
       QScrollBar *p_scroll_bar = this->verticalScrollBar();
       bool bool_at_bottom = (p_scroll_bar->value() == p_scroll_bar->maximum());
    
       if (!check_nl){
          QTextCursor text_cursor = QTextCursor(this->document());
          text_cursor.movePosition(QTextCursor::End);
          text_cursor.insertText(text);
       } else {
          QTextCursor text_cursor = QTextCursor(this->document());
          text_cursor.beginEditBlock();
    
          text_cursor.movePosition(QTextCursor::End);
    
          QStringList string_list = text.split('\n');
    
          for (int i = 0; i < string_list.size(); i++){
             text_cursor.insertText(string_list.at(i));
             if ((i + 1) < string_list.size()){
                text_cursor.insertBlock();
             }
          }
    
    
          text_cursor.endEditBlock();
       }
    
       if (bool_at_bottom){
          p_scroll_bar->setValue(p_scroll_bar->maximum());
       }
    }
    
    /**
     * append html without adding new line (new paragraph)
     *
     * @param html       html text to append
     * @param check_br   if true, then text will be splitted by "<br>" tag,
     *                   and each substring will be added as separate QTextBlock.
     *                   NOTE: this important: if you set this to false,
     *                   then you should append new blocks manually (say, by calling appendNL() )
     *                   because one huge block will significantly slow down your widget.
     */
    void QPlainTextEdit_My::appendHtmlNoNL(const QString &html, bool check_br)
    {
       QScrollBar *p_scroll_bar = this->verticalScrollBar();
       bool bool_at_bottom = (p_scroll_bar->value() == p_scroll_bar->maximum());
    
       if (!check_br){
          QTextCursor text_cursor = QTextCursor(this->document());
          text_cursor.movePosition(QTextCursor::End);
          text_cursor.insertHtml(html);
       } else {
    
          QTextCursor text_cursor = QTextCursor(this->document());
          text_cursor.beginEditBlock();
    
          text_cursor.movePosition(QTextCursor::End);
    
          QStringList string_list = html.split(QRegExp("\\<br\\s*\\/?\\>", Qt::CaseInsensitive));
    
          for (int i = 0; i < string_list.size(); i++){
             text_cursor.insertHtml( string_list.at(i) );
             if ((i + 1) < string_list.size()){
                text_cursor.insertBlock();
             }
          }
    
          text_cursor.endEditBlock();
       }
    
       if (bool_at_bottom){
          p_scroll_bar->setValue(p_scroll_bar->maximum());
       }
    }
    
    /**
     * Just insert new QTextBlock to the text.
     * (in fact, adds new paragraph)
     */
    void QPlainTextEdit_My::insertNL()
    {
       QScrollBar *p_scroll_bar = this->verticalScrollBar();
       bool bool_at_bottom = (p_scroll_bar->value() == p_scroll_bar->maximum());
    
       QTextCursor text_cursor = QTextCursor(this->document());
       text_cursor.movePosition(QTextCursor::End);
       text_cursor.insertBlock();
    
       if (bool_at_bottom){
          p_scroll_bar->setValue(p_scroll_bar->maximum());
       }
    }
    

    I'm confused because in original code there are much more complicated calculations of atBottom:

    const bool atBottom =  q->isVisible()
                           && (control->blockBoundingRect(document->lastBlock()).bottom() - verticalOffset()
                               <= viewport->rect().bottom());
    

    and needScroll:

    if (atBottom) {
        const bool needScroll =  !centerOnScroll
                                 || control->blockBoundingRect(document->lastBlock()).bottom() - verticalOffset()
                                 > viewport->rect().bottom();
        if (needScroll)
            vbar->setValue(vbar->maximum());
    }
    

    But my easy solution seems to work too.

    0 讨论(0)
  • 2020-11-29 05:47

    I'll just quote what I found here:

    http://www.jcjc-dev.com/2013/03/qt-48-appending-text-to-qtextedit.html


    We just need to move the cursor to the end of the contents in the QTextEdit and use insertPlainText. In my code, it looks like this:

    myTextEdit->moveCursor (QTextCursor::End);
    myTextEdit->insertPlainText (myString);
    myTextEdit->moveCursor (QTextCursor::End);
    

    As simple as that. If your application needs to keep the cursor where it was before appending the text, you can use the QTextCursor::position() and QTextCursor::setPosition() methods, or

    just copying the cursor before modifying its position [QTextCursor QTextEdit::textCursor()] and then setting that as the cursor [void QTextEdit::setTextCursor(const QTextCursor & cursor)].

    Here’s an example:

    QTextCursor prev_cursor = myTextEdit->textCursor();
    myTextEdit->moveCursor (QTextCursor::End);
    myTextEdit->insertPlainText (myString);
    myTextEdit->setTextCursor (&prev_cursor);
    
    0 讨论(0)
  • 2020-11-29 05:52

    Like any string:

    QTextEdit *myTextEdit = ui->textEdit;
    myTextEdit->moveCursor (QTextCursor::End);
    myTextEdit->insertPlainText (myString+"\n");
    

    I tried it and it worked.

    0 讨论(0)
提交回复
热议问题