I've researched this extensively but haven't found a satisfactory solution yet:
How do I append text at the end of QTextEdit widget without triggering a scroll to the bottom of the widget when either of these conditions is met:
(In all other cases, a scroll to the bottom of the QTextEdit widget should be triggered.)
Here is the code I'm currently using to append text
at the bottom of a QTextEdit widget
:
const QTextCursor old_cursor = widget.textCursor();
widget.moveCursor(QTextCursor::End);
widget.textCursor().insertText(text);
if (old_cursor.hasSelection())
widget.setTextCursor(old_cursor);
else widget.moveCursor(QTextCursor::End);
This partially takes care of condition 1: the problem is that the view will still scroll until only the last line of the selection is visible, at which point it will indeed stop scrolling.
Condition 2 is not taken care of at all: some posts suggest to save the position of the vertical scrollbar and restore it after the text was appended, however I don't think this is correct since the scrollbar should move upward when text is appended, even though the view stays still.
Note that I'm using QTextCursor::insertText()
instead of QTextEdit::append()
because I need to adjust the color of the text being appended, regardless of whether the user has selected text or not.
Update: Here is the code I ended up with, thanks to Pavel's answer:
const QTextCursor old_cursor = widget.textCursor();
const int old_scrollbar_value = widget.verticalScrollBar()->value();
const bool is_scrolled_down = old_scrollbar_value == widget.verticalScrollBar()->maximum();
// Move the cursor to the end of the document.
widget.moveCursor(QTextCursor::End);
// Insert the text at the position of the cursor (which is the end of the document).
widget.textCursor().insertText(text);
if (old_cursor.hasSelection() || !is_scrolled_down)
{
// The user has selected text or scrolled away from the bottom: maintain position.
widget.setTextCursor(old_cursor);
widget.verticalScrollBar()->setValue(old_scrollbar_value);
}
else
{
// The user hasn't selected any text and the scrollbar is at the bottom: scroll to the bottom.
widget.moveCursor(QTextCursor::End);
widget.verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}
QTextEdit: scroll down automatically only if the scrollbar is at the bottom. There's a QTextEdit that displays quite a lot of text. It is NOT editable. Suppose I want to read something around the beginning, scroll up, but then a new line is added and the scrollbar automatically goes to the bottom.
method. But result was exactly the same as with a default scroll bar - scroll bar is still dependent from the text. In the end I added the QScrollBar as a child to QTextEdit like this : , but I have to synchronize scroll bar size and position with parent widget manually, and it's bad.
, is such , that from one hand does not depend from the QTextEdit content , and from the other hand depend from its size. ( I've tried to put my scroll bar into internal QTextEdit layout , but I can't get access to it. ) Thanks.
If you want to set a selection in QTextEdit just create one on a QTextCursor object and then make that cursor the visible cursor using setTextCursor () . The selection can be copied to the clipboard with copy () , or cut to the clipboard with cut () . The entire text can be selected using selectAll () .
Saving and restoring scrollbar position is quite correct and works perfectly. When document's length is increased, scrollbar's maximum value is increased. But its value is still equal to number of pixels above the viewport. So when you add contents to the document and set the same scrollbar value repeatadly, scrollbar's handle will move to the top, but the content will remain immobile.
It seems that you already know how to check if the user has selected some text. To check if the user has scrolled away from the bottom, you should simply compare vertical scrollbar's value with its maximum.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With