¿Cómo agregar texto a QPlainTextEdit sin agregar nueva línea y mantener el desplazamiento en la parte inferior?

Necesito agregar texto a QPlainTextEdit sin agregar una nueva línea al texto, pero ambos métodos appendPlainText() y appendHtml() agregan un párrafo realmente nuevo.

Puedo hacerlo manualmente con QTextCursor :

 QTextCursor text_cursor = QTextCursor(my_plain_text_edit->document()); text_cursor.movePosition(QTextCursor::End); text_cursor.insertText("string to append. "); 

Eso funciona, pero también necesito mantener el desplazamiento en la parte inferior si estaba en la parte inferior antes de agregar.

Traté de copiar la lógica de las fonts de Qt, pero me quedé, porque en realidad se QPlainTextEditPrivate clase QPlainTextEditPrivate , y no puedo encontrar la manera de hacer lo mismo sin ella: decir, no veo el método verticalOffset() en QPlainTextEdit .

En realidad, estas fonts contienen muchas cosas raras (a primera vista, al menos), y no tengo idea de cómo implementar esto.

Aquí está el código fuente de append() : http://code.qt.io/cgit/qt/qt.git/tree/src/gui/widgets/qplaintextedit.cpp#n2763

Voy a citar lo que encontré aquí:

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


Solo tenemos que mover el cursor hasta el final de los contenidos en QTextEdit y usar insertPlainText. En mi código, se ve así:

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

Tan sencillo como eso. Si su aplicación necesita mantener el cursor donde estaba antes de agregar el texto, puede usar los QTextCursor::position() y QTextCursor::setPosition() , o

simplemente copiando el cursor antes de modificar su posición [QTextCursor QTextEdit::textCursor()] y luego estableciendo eso como el cursor [void QTextEdit::setTextCursor(const QTextCursor & cursor)] .

Aquí hay un ejemplo:

 QTextCursor prev_cursor = myTextEdit->textCursor(); myTextEdit->moveCursor (QTextCursor::End); myTextEdit->insertPlainText (myString); myTextEdit->setTextCursor (&prev_cursor); 

La respuesta actual no era una opción para mí. Fue mucho más simple agregar html sin líneas nuevas con el siguiente método.

 //logs is a QPlainTextEdit object ui.logs->moveCursor(QTextCursor::End); ui.logs->textCursor().insertHtml(out); ui.logs->moveCursor(QTextCursor::End); 

Ok, no estoy seguro si mi solución es realmente “buena”, pero parece funcionar para mí: acabo de hacer una nueva clase QPlainTextEdit_My heredada de QPlainTextEdit , y agregué nuevos métodos appendPlainTextNoNL() , appendHtmlNoNL() , insertNL() .

Por favor, check_nl : lea los comentarios sobre params check_nl y check_br cuidado, ¡esto es importante! Pasé varias horas para descubrir por qué mi widget es tan lento cuando añado texto sin nuevos párrafos.

 /****************************************************************************************** * INCLUDED FILES *****************************************************************************************/ #include "qplaintextedit_my.h" #include  #include  #include  #include  /****************************************************************************************** * 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 "
" 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("\\", 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()); } }

Estoy confundido porque en el código original hay cálculos mucho más complicados de atBottom :

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

y needScroll :

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

Pero mi solución fácil parece funcionar también.

Como cualquier cadena:

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

Lo intenté y funcionó.