2012-11-26 36 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() in QPlainTextEdit

實際上,這些資源包含很多奇怪的東西(至少在第一眼看起來),我不知道如何實現它。

這裏是append()源代碼:http://code.qt.io/cgit/qt/qt.git/tree/src/gui/widgets/qplaintextedit.cpp#n2763

回答

2

好吧,我不知道如果我的解決辦法其實是「好」,但它似乎爲我工作:我只是做了從QPlainTextEdit繼承新類QPlainTextEdit_My,並增加了新的方法appendPlainTextNoNL(),appendHtmlNoNL(),insertNL()

請注意:請仔細閱讀關於params 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


我們只需將光標移動到在的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); 
+1

A小調校正,setTextCursor需要QTextCursor,不是指針。來源:http://doc.qt.io/qt-4.8/qplaintextedit.html#setTextCursor。此外,您的鏈接已關閉。 – awakenDeepBlue

8

目前的答案是不是我的選擇。用下面的方法添加html並沒有新行是非常簡單的。

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

這個答案是不是我的選擇,因爲:(1)該公司密切關注新的數據向下滾動,即使當前的滾動位置不是底部。這非常煩人:當新數據到達時,用戶無法檢查之前添加的數據; (2)當新數據到達時,它清除用戶的選擇。也許,在某些情況下,這種行爲是可以接受的,但對我來說,這是非常用戶不友好。 –

-2

像任何字符串:

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

我想它和它的工作。

+0

請使用4位在前面的代碼格式化爲代碼。 –

+0

已經給出了這個答案。 –

相關問題