如何在不添加换行符的情况下将文本附加到QPlainTextEdit,并保持滚动到底部? [英] How to append text to QPlainTextEdit without adding newline, and keep scroll at the bottom?

查看:279
本文介绍了如何在不添加换行符的情况下将文本附加到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。);

这样可以工作,但是我还需要保持滚动到底部,如果它在底部附加。 / p>

我试图从Qt的源代码复制逻辑,但我坚持,因为实际上使用了 QPlainTextEditPrivate 我没有找到办法做同样没有它:说,我没有看到方法 verticalOffset() QPlainTextEdit



实际上,这些源包含许多奇怪的(至少在第一次看),我不知道如何实现这个。 p>

这是 append()的源代码 http://code.qt.io/cgit/qt/qt.git/tree/src/ gui / widgets / qplaintextedit.cpp#n2763

解决方案

好的,我不知道我的解决方案是否nice,但它似乎为我工作:我只是做了 QPlainTextEdit_My 继承自 QPlainTextEdit 新方法 appendPlainTextNoNL() appendHtmlNoNL() insertNL() $ c> check_br 仔细,这很重要!我花了几个小时来找出当我添加没有新段落的文本时为什么我的小部件这么慢。

  / **** **************************************************** ************************************ 
*包含文件
*** **************************************************** ************************************ /

#includeqplaintextedit_my。 h
#include< QScrollBar>
#include< QTextCursor>
#include< QStringList>
#include< QRegExp>


/ *********************************** **************************************************** ***
* CONSTRUCTOR,DESTRUCTOR
*********************************** **************************************************** **** /

QPlainTextEdit_My :: QPlainTextEdit_My(QWidget * parent):
QPlainTextEdit(parent)
{

}
b $ b QPlainTextEdit_My :: QPlainTextEdit_My(const QString& text,QWidget * parent):
QPlainTextEdit(text,parent)
{

}
$ b b / ************************************************ ******************************************
* METHODS
************************************************ ***************************************** /

/ * private * /

/ * protected * /

/ * public * /

/ **
*添加新行(新段落)
*
* @param html html文本以附加
* @param check_nl如果为true,则文本将由\\\
char,
*,每个子字符串将作为单独的QTextBlock添加。
*注意:这很重要:如果你设置为false,
*,你应该手动添加新的块(例如,通过调用appendNL())
*因为一个巨大的块会显着减慢下来你的小部件。
* /
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('\\\
');

for(int i = 0; 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());
}
}

/ **
*添加html而不添加新行(新段落)
*
* @param html html文本附加
* @param check_br如果为true,则文本将由< br>拆分标签,
*,每个子字符串将作为单独的QTextBlock添加。
*注意:这很重要:如果你设置为false,
*,你应该手动添加新的块(例如,通过调用appendNL())
*因为一个巨大的块会显着减慢下来你的小部件。
* /
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 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());
}
}

/ **
*只需在文本中插入新的QTextBlock即可。
*(实际上,添加了新段落)
* /
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

needScroll

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

但我的简单解决方案似乎也有效。


I need to append text to QPlainTextEdit without adding a newline to the text, but both methods appendPlainText() and appendHtml() adds actually new paragraph.

I can do that manually with QTextCursor:

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

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

That works, but I also need to keep scroll at bottom if it was at bottom before append.

I tried to copy logic from Qt's sources, but I stuck on it, because there actually QPlainTextEditPrivate class is used, and I can't find the way to do the same without it: say, I don't see method verticalOffset() in QPlainTextEdit.

Actually, these sources contain many weird (at the first look, at least) things, and I have no idea how to implement this.

Here's the source code of append(): http://code.qt.io/cgit/qt/qt.git/tree/src/gui/widgets/qplaintextedit.cpp#n2763

解决方案

Ok, I'm not sure if my solution is actually "nice", but it seems to work for me: I just made new class QPlainTextEdit_My inherited from QPlainTextEdit, and added new methods appendPlainTextNoNL(), appendHtmlNoNL(), insertNL().

Please NOTE: read comments about params check_nl and check_br carefully, this is important! I spent several hours to figure out why is my widget so slow when I append text without new paragraphs.

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

I'm confused because in original code there are much more complicated calculations of atBottom:

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

and needScroll:

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

But my easy solution seems to work too.

这篇关于如何在不添加换行符的情况下将文本附加到QPlainTextEdit,并保持滚动到底部?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆