有选择时阻止QTextEdit窗口小部件滚动

时间:2014-02-22 14:54:56

标签: c++ qt scroll qtextedit qtextcursor

我对此进行了广泛的研究,但尚未找到令人满意的解决方案:

当满足以下任一条件时,如何在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(),因为我需要调整要追加的文字的颜色,无论用户是否选择了文字。


更新:这是我最终得到的代码,感谢Pavel的回答:

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

1 个答案:

答案 0 :(得分:4)

保存和恢复滚动条位置非常正确并且工作正常。当文档的长度增加时,滚动条的最大值会增加。但它的值仍然等于视口上方的像素数。因此,当您向文档添加内容并重复设置相同的滚动条值时,滚动条的句柄将移至顶部,但内容将保持不动。

您似乎已经知道如何检查用户是否选择了某些文字。要检查用户是否已从底部滚动,您只需将垂直滚动条的值与其最大值进行比较。