2012-11-26 52 views
23

テキストに改行を追加せずにQPlainTextEditにテキストを追加する必要がありますが、両方のメソッドappendPlainText()appendHtml()が実際に新しい段落を追加します。改行を追加せずにQPlainTextEditにテキストを追加する方法と、スクロールを一番下に置く方法はありますか?

私は QTextCursorを使って手動でそれを行うことができ

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

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

動作しますが、私はまた、追記前の一番下にあった場合は下部のスクロールを維持する必要があります。

私はQtのソースからロジックをコピーしようとしましたが、実際にはQPlainTextEditPrivateクラスが使用されているので、私はそれに固執しました。そして、それがなければ同じことをする方法を見つけることができません。 verticalOffset()QPlainTextEditに設定します。

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

append()のソースコードです:http://code.qt.io/cgit/qt/qt.git/tree/src/gui/widgets/qplaintextedit.cpp#n2763

答えて

2

[OK]を、私は私の解決策は、実際に「ナイス」であるかどうかわからないんだけど、私のために働くようだ:私はちょうどQPlainTextEditから継承された新しいクラスQPlainTextEdit_Myを作りました、新しいメソッドを追加しましたappendPlainTextNoNL(),,insertNL()

注:は、check_nlcheck_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()); 
} 

は、しかし、私の簡単な解決策は、あまりにも動作するようです。

+1

少なくともQt 5.2.1では、insertPlainText()/ text_cursor.insertText()は、改行に遭遇したときにブロックを自動的に挿入するようです。 – iliis

19

私はちょうど私がここに見つけたものを引用します:

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


は、私達はちょうどinsertPlainTextをQTextEdit内のコンテンツの末尾にカーソルを移動して使用する必要があります。私のコードでは、次のようになります。

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

それだけではありません。あなたのアプリケーションは、それがテキストを追加する前にしたカーソルを維持する必要がある場合は、単にその位置[QTextCursor QTextEdit::textCursor()]を変更して、カーソル[void QTextEdit::setTextCursor(const QTextCursor & cursor)]としてそれを設定する前に、カーソルをコピーQTextCursor::position()QTextCursor::setPosition()方法、または

を使用することができます。ここで

は例です:

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

小さな修正ですが、setTextCursorはポインタではなくQTextCursorをとります。出典:http://doc.qt.io/qt-4.8/qplaintextedit.html#setTextCursorあなたのリンクもダウンしています。 – awakenDeepBlue

8

現在の回答が私のためのオプションではありませんでした。次のメソッドを使用して、新しい行がないhtmlを追加する方がはるかに簡単でした。

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

私はそれを試してみましたし、それが働いた:任意の文字列と同様に

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

この答えは私のための選択肢ではありません:(1)現在のスクロール位置が最下部になくても新しいデータをスクロールダウンし続けます。これは非常に面倒です。新しいデータが到着する間に、ユーザーは以前に追加されたデータを調べることができません。 (2)新しいデータが到着すると、ユーザーの選択がクリアされます。おそらく、場合によってはこの動作は許容されますが、私の場合は非常にユーザーフレンドリーです。 –

-2

+0

コードの前に4つのスペースを入れてコードとしてフォーマットしてください。 –

+0

この回答は既に与えられています。 –

関連する問題