Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Custom component in ScrollView



  • This is a counterpart to another question I have asked, about how to get a non-attached ScrollBar to respond to wheel events. There I have assumed that I cannot use ScrollView to implement scrolling of my component. Maybe I am wrong so let me ask a different question...

    What does a component need to provide so that it will work in a ScrollView? I understand that it should provide a contentHeight and contentWidth and that will tell the ScrollView the actual bounds of the item to be scrolled over. But what about tying the scroll bar positions to the item?

    In my case I am subclassing QQuickPaintedItem to draw a large area of text. My paint method draws in the rectangle defined by the height and width properties of the item and I have exposed specific properties that define an offset within the full area of text so that I know which part of the text to draw. I then bind these properties to the scroll bars' positions.

    If I wanted to make my component work inside a ScrollView how would the ScrollView normally expect to communicate to the content item what the scroll bar positions are so that the content item is painted correctly?


  • Qt Champions 2018

    Do you want to paint the part only displayed in the viewport of the ScrollView in your contentItem?



  • @GrecKo yes, that's right. The question is how my component knows where the ScrollView viewport currently is. I know what the height and width are but I presume that there is a standard way that ScrollView communicates the offset of the viewport.



  • @GrecKo Another way to put it: for a normal component that functions correctly in a ScrollView how does it know which part to paint? This will have some relationship to the ScrollView's scrollbar position but obviously the component does not know about ScrollView.


  • Qt Champions 2018

    A normal component in a ScrollView paints everything, even what's not displayed, it just get moved by the ScrollView.

    I guess you don't want that as a kind of optimization.
    You could add a rect property in your component to make it aware of the viewport needed to be rendered.
    You can access it via the contentItem of the ScrollView, which is a Flickable.
    Your item will be parent to the contentItem of the Flickable ( so the contentItem of the contentItem of the ScrollView :P)
    I would do something like that:

    ScrollView {
        id: scrollView
        CustomItem {
            viewport: Qt.rect(scrollView.contentItem.contentX, scrollView.contentItem.contentY, scrollView.width, scrollView.height)
        }
    }
    

    and in your paint method, only paint what's inside the viewport.



  • @GrecKo Thank you! I have not tried this yet but the contentItem.contentX|Y seems like the piece I was missing.

    Also, thank you for clarifying how ScrollView works, in that in fact it paints the whole area. My custom component is a simplified replacement for a read-only TextArea which needs to handle 1000s of lines of text but is obviously only displaying a few at a time. The whole point of what I am doing is to limit the paints to the area needed because TextArea itself performs so poorly (particularly in handling incremental updates once the text is beyond a certain length).



  • @GrecKo I tried the suggested approach but it seems that it is quite well baked into ScrollView that it expects the whole thing to be painted. There might be a way to get it to work but it's beyond my current level of expertise. I guess I am back to rolling my own ScrollView-like behaviour which, to be fair, I have working reasonably well; it's just the lack of wheel response on the vertical scrollbar that is the issue. I guess I could implement my own ScrollBar from scratch...


Log in to reply