TextArea in a Flickable resets scroll position when contents change.
-
I have a TextArea in a Flickable that is being used to display an output log. The text is coming from a c++ backend.
My issue is that whenever the c++ backend changes the text contents, the scrollbar resets to the top.
I have figured out how to capture the dataChanged signal and use that to scroll the text to the bottom so the user can see the text as it comes in.
I would also like the option to keep the display at the same scrolling position when new text is appended to the bottom of the log.
Here's some relevant code...
Flickable { id: flickable anchors.fill: dataViewerText TextArea.flickable: TextArea { text: dataViewerBackend.text wrapMode: TextArea.Wrap readOnly: true padding: 4 font.family: "Courier New" font.pixelSize: 12 } ScrollBar.vertical: ScrollBar { id: dataViewerTextScrollbar } }
The c++ backend is nothing remarkable
class DataViewerBackend : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(QString text MEMBER m_dataViewerText NOTIFY dataViewerTextChanged)
... -
@preiter not sure, but...since you've intercepted the signal, can you store the position property of the ScrollBar, and reset it after you change the contents of the Flickable?
That's my current solution and it seems to be working, but it's ugly. You have to correct for the fact that the size of the content has changed, so it's something like:
newPosition = oldPosition * newSize / oldSize
...
I think I'm going to change it from a simple string in a TextArea to a ListModel/ListView so that I can use the beginInsertRows() / endInsertRows() signals which should preserve the scroll location.
-
I have a TextArea in a Flickable that is being used to display an output log. The text is coming from a c++ backend.
My issue is that whenever the c++ backend changes the text contents, the scrollbar resets to the top.
I have figured out how to capture the dataChanged signal and use that to scroll the text to the bottom so the user can see the text as it comes in.
I would also like the option to keep the display at the same scrolling position when new text is appended to the bottom of the log.
Here's some relevant code...
Flickable { id: flickable anchors.fill: dataViewerText TextArea.flickable: TextArea { text: dataViewerBackend.text wrapMode: TextArea.Wrap readOnly: true padding: 4 font.family: "Courier New" font.pixelSize: 12 } ScrollBar.vertical: ScrollBar { id: dataViewerTextScrollbar } }
The c++ backend is nothing remarkable
class DataViewerBackend : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(QString text MEMBER m_dataViewerText NOTIFY dataViewerTextChanged)
... -
@preiter not sure, but...since you've intercepted the signal, can you store the position property of the ScrollBar, and reset it after you change the contents of the Flickable?
That's my current solution and it seems to be working, but it's ugly. You have to correct for the fact that the size of the content has changed, so it's something like:
newPosition = oldPosition * newSize / oldSize
...
I think I'm going to change it from a simple string in a TextArea to a ListModel/ListView so that I can use the beginInsertRows() / endInsertRows() signals which should preserve the scroll location.
-
-
That's my current solution and it seems to be working, but it's ugly. You have to correct for the fact that the size of the content has changed, so it's something like:
newPosition = oldPosition * newSize / oldSize
...
I think I'm going to change it from a simple string in a TextArea to a ListModel/ListView so that I can use the beginInsertRows() / endInsertRows() signals which should preserve the scroll location.
@preiter said in TextArea in a Flickable resets scroll position when contents change.:
think I'm going to change it from a simple string in a TextArea to a ListModel/ListView
Yeah, I was thinking about that, too. If the information in your TextArea is at all of a list variety, that's probably a better way to go anyway. After all, if the entire contents were to change (for example), keeping the original scroll position doesn't make much sense anyway.