web-dev-qa-db-ja.com

改行を追加せずにQPlainTextEditにテキストを追加し、下部にスクロールし続ける方法は?

テキストに改行を追加せずにQPlainTextEditにテキストを追加する必要がありますが、appendPlainText()appendHtml()の両方のメソッドは実際に新しい段落を追加します。

QTextCursorを使用して手動で行うことができます。

_QTextCursor text_cursor = QTextCursor(my_plain_text_edit->document());
text_cursor.movePosition(QTextCursor::End);

text_cursor.insertText("string to append. ");
_

それは機能しますが、追加する前に下部にあった場合は下部にスクロールする必要もあります。

私はQtのソースからロジックをコピーしようとしましたが、実際にはQPlainTextEditPrivateクラスが使用されているため、それにこだわっており、それなしで同じことを行う方法を見つけることができません:たとえば、私は表示されませんQPlainTextEditのメソッドverticalOffset()

実際、これらのソースには多くの奇妙な(少なくとも一見)ものが含まれており、これを実装する方法がわかりません。

append()のソースコードを以下に示します。 http://code.qt.io/cgit/qt/qt.git/tree/src/gui/widgets/qplaintextedit.cpp#n276 =

28
Dmitry Frank

OK、私の解決策が実際に「いい」かどうかはわかりませんが、うまくいくようです:新しいクラス_QPlainTextEdit_My_をQPlainTextEditから継承し、新しいメソッドappendPlainTextNoNL()appendHtmlNoNL()insertNL()

注意:パラメータ_check_nl_および_check_br_に関するコメントを注意深く読んでください。これは重要です!新しい段落なしでテキストを追加すると、ウィジェットが非常に遅い理由を理解するために数時間を費やしました。

_/******************************************************************************************
 * 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());
   }
}
_

元のコードにはatBottomのはるかに複雑な計算があるため、私は混乱しています:

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

およびneedScroll

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

しかし、私の簡単な解決策もうまくいくようです。

4
Dmitry Frank

ここで見つけたものを引用します。

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


QTextEditのコンテンツの最後にカーソルを移動し、insertPlainTextを使用するだけです。私のコードでは、次のようになります。

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

それと同じくらい簡単です。アプリケーションでテキストを追加する前にカーソルを保持する必要がある場合は、QTextCursor::position()およびQTextCursor::setPosition()メソッドを使用できます。または、

カーソルの位置を変更する前にカーソルをコピーして[QTextCursor QTextEdit::textCursor()]し、それをカーソル[void QTextEdit::setTextCursor(const QTextCursor & cursor)]として設定します。

以下に例を示します。

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

現在の回答は私にとって選択肢ではありませんでした。次の方法を使用して、改行なしでhtmlを追加する方がはるかに簡単でした。

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

任意の文字列のように:

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

私はそれを試してみたが、うまくいった。

0
Nabil