This question has been asked before but only regarding the cursor position as it seems..
I've implemented some kind of auto-load-on-change text editor based on QTextEdit
. Problem is: when I apply the newly loaded text using
self.my_editor.setPlainText(new_text)
the cursor will jump to position 0
, which is very uncomfortable.
Of course I'm not the only one who feels this way so people already asked how they could restore the cursor after applying the new text, e.g. here: https://www.qtcentre.org/threads/13933-Restoring-cursor-position-in-QTextEdit
But the answers I found only cover the position of the text cursor itself.
For example this code would save the cursor, set the new text and restore the cursor:
c = self.my_editor.textCursor()
p = c.position()
self.my_editor.setPlainText(new_text)
c.setPosition(p)
self.my_editor.setTextCursor(c)
But now effectively the editor would scroll to position 0
and then down again to be able to show the cursor at the restored position. So visually the editor jumps about (which is still better than losing the cursor, though)
Is there a way to also store the visual area of the QTextEdit
instance? Of course in case the text content has really changed it's all but trivial to minimize the visual jumping but shouldn't it be possible to see no jumping at all in case the text has change behind the cursor?
Assuming that the contents are always almost the same, you can store the values of the scroll bars, and then set them after updating the text:
c = self.my_editor.textCursor()
p = c.position()
hPos = self.my_editor.horizontalScrollBar().value()
vPos = self.my_editor.verticalScrollBar().value()
self.my_editor.setPlainText(new_text)
c.setPosition(p)
self.my_editor.horizontalScrollBar().setValue(hPos)
self.my_editor.verticalScrollBar().setValue(vPos)
self.my_editor.setTextCursor(c)
The order of scroll bar and cursor reset depends on your needs: if the cursor could be outside the visible viewport, you might prefer to set the cursor first and then restore the scroll bars.
Finally, if the contents could change a lot more, you should use ratios based on the scroll bars maximum values:
try:
hBar = self.my_editor.horizontalScrollBar()
hPos = hBar.value() / hBar.maximum()
except ZeroDivisionError:
hPos = 0
try:
vBar = self.my_editor.verticalScrollBar()
vPos = vBar.value() / vBar.maximum()
except ZeroDivisionError:
vPos = 0
self.my_editor.setPlainText(new_text)
c.setPosition(p)
self.my_editor.setTextCursor(c)
hBar.setValue(hPos * hBar.maximum())
vBar.setValue(vPos * vBar.maximum())
Note: the maximum values must be used dynamically, as the range could change when the text changes.