Je dois ajouter du texte à QPlainTextEdit
sans ajouter de nouvelle ligne au texte, mais les deux méthodes appendPlainText()
et appendHtml()
ajoutent un nouveau paragraphe.
Je peux le faire manuellement avec QTextCursor
:
QTextCursor text_cursor = QTextCursor(my_plain_text_edit->document());
text_cursor.movePosition(QTextCursor::End);
text_cursor.insertText("string to append. ");
Cela fonctionne, mais je dois aussi garder le parchemin en bas s'il était en bas avant append.
J'ai essayé de copier la logique à partir des sources de Qt, mais je suis restée bloquée là-dessus, car la classe QPlainTextEditPrivate
est utilisée et je ne trouve pas le moyen de faire la même chose sans elle: disons que je ne vois pas la méthode verticalOffset()
dans QPlainTextEdit
.
En fait, ces sources contiennent de nombreuses choses étranges (du moins au premier abord), et je ne sais pas du tout comment les mettre en œuvre.
Voici le code source de append()
: http://code.qt.io/cgit/qt/qt.git/tree/src/gui/widgets/qplaintextedit.cpp#n2763
Ok, je ne suis pas sûr si ma solution est réellement "agréable", mais cela semble fonctionner pour moi: je viens de créer une nouvelle classe QPlainTextEdit_My
héritée de QPlainTextEdit
et d’ajouter de nouvelles méthodes appendPlainTextNoNL()
, appendHtmlNoNL()
, insertNL()
.
S'il vous plaît NOTE: lire les commentaires sur params check_nl
et check_br
avec soin, c'est important! J'ai passé plusieurs heures à comprendre pourquoi mon widget est si lent lorsque j'ajoute du texte sans nouveaux paragraphes.
/******************************************************************************************
* 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());
}
}
Je suis confus parce que dans le code original, il existe des calculs beaucoup plus compliqués de atBottom
:
const bool atBottom = q->isVisible()
&& (control->blockBoundingRect(document->lastBlock()).bottom() - verticalOffset()
<= viewport->rect().bottom());
et needScroll
:
if (atBottom) {
const bool needScroll = !centerOnScroll
|| control->blockBoundingRect(document->lastBlock()).bottom() - verticalOffset()
> viewport->rect().bottom();
if (needScroll)
vbar->setValue(vbar->maximum());
}
Mais ma solution facile semble fonctionner aussi.
Je vais juste citer ce que j'ai trouvé ici:
http://www.jcjc-dev.com/2013/03/qt-48-appending-text-to-qtextedit.html
Il suffit de déplacer le curseur à la fin du contenu de QTextEdit et d’utiliser insertPlainText. Dans mon code, cela ressemble à ceci:
myTextEdit->moveCursor (QTextCursor::End);
myTextEdit->insertPlainText (myString);
myTextEdit->moveCursor (QTextCursor::End);
Aussi simple que cela. Si votre application doit conserver le curseur où elle était avant d'ajouter le texte, vous pouvez utiliser les méthodes QTextCursor::position()
et QTextCursor::setPosition()
, ou
il suffit de copier le curseur avant de modifier sa position [QTextCursor QTextEdit::textCursor()]
, puis de le définir comme curseur [void QTextEdit::setTextCursor(const QTextCursor & cursor)]
.
Voici un exemple:
QTextCursor prev_cursor = myTextEdit->textCursor();
myTextEdit->moveCursor (QTextCursor::End);
myTextEdit->insertPlainText (myString);
myTextEdit->setTextCursor (&prev_cursor);
La réponse actuelle n'était pas une option pour moi. Il était beaucoup plus simple d'ajouter du code HTML sans nouvelles lignes avec la méthode suivante.
//logs is a QPlainTextEdit object
ui.logs->moveCursor(QTextCursor::End);
ui.logs->textCursor().insertHtml(out);
ui.logs->moveCursor(QTextCursor::End);
Comme n'importe quelle corde:
QTextEdit *myTextEdit = ui->textEdit;
myTextEdit->moveCursor (QTextCursor::End);
myTextEdit->insertPlainText (myString+"\n");
Je l'ai essayé et cela a fonctionné.