Я тщательно исследовал это, но пока не нашел удовлетворительного решения:
Как добавить текст в конец виджета QTextEdit, не вызывая прокрутку в нижней части виджета, когда выполняется одно из следующих условий:
(Во всех остальных случаях должна быть запущена прокрутка к нижней части виджета QTextEdit.)
Вот код, который я сейчас использую для добавления text
внизу 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);
Это частично учитывает условие 1: проблема в том, что представление будет по-прежнему прокручиваться до тех пор, пока не будет видна только последняя строка выделения, после чего оно действительно прекратит прокрутку.
Условие 2 вообще не выполняется: в некоторых сообщениях предлагается сохранить положение вертикальной полосы прокрутки и восстановить ее после добавления текста, однако я не думаю, что это правильно, поскольку полоса прокрутки должна двигаться вверх при добавлении текста, хотя вид остается на месте.
Обратите внимание, что я использую QTextCursor::insertText()
вместо QTextEdit::append()
потому что мне нужно настроить цвет добавляемого текста, независимо от того, выбрал ли пользователь текст или нет.
ОбновитьВот код, которым я закончил, благодаря ответу Павла:
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());
}
Сохранение и восстановление положения полосы прокрутки вполне корректно и работает отлично. При увеличении длины документа максимальное значение полосы прокрутки увеличивается. Но его значение все равно равно количеству пикселей над окном просмотра. Поэтому, когда вы добавляете содержимое в документ и повторно устанавливаете одно и то же значение полосы прокрутки, ручка полосы прокрутки переместится вверх, но содержимое останется неподвижным.
Кажется, вы уже знаете, как проверить, выбрал ли пользователь какой-либо текст. Чтобы проверить, прокрутил ли пользователь снизу, вы должны просто сравнить значение вертикальной полосы прокрутки с ее максимумом.
Других решений пока нет …