Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to get ScrollView to scroll when children are reparented into it?

How to get ScrollView to scroll when children are reparented into it?

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
26 Posts 4 Posters 3.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    Vadi2
    wrote on last edited by Vadi2
    #1

    I'm reparenting a TextArea into a ScrollView - somewhat unsuccessfully, because the said ScrollView then refuses to scroll.

    What is the right way to go about it? I've stripped the problem down to a small, reproducible usecase here: https://transfer.sh/rYfth/dodgy-scrollview.zip

    And here is the qml file inside that zip in full:

    import QtQuick 2.7
    import QtQuick.Controls 2.5
    import QtQuick.Controls.Material 2.0
    import QtQuick.Window 2.10
    import QtQuick.Controls.Universal 2.12
    import QtQuick.Layouts 1.12
    import QtQuick.Dialogs 1.3
    
    ApplicationWindow {
        id: window
        visible: true
        width: 640; height: 480
        minimumWidth: 550; minimumHeight: 300
        title: qsTr("Hammer")
    
        Page {
            id: addResourcesPage
            width: window.width
            height: window.height - buttonsRow.height
    
    
            ScrollView {
                id: addResourceScrollView
                height: parent.height; width: parent.width;
                visible: textArea.state === "EXPANDED"
                clip: true
    
                onContentHeightChanged: console.log(`content height changed`)
                onContentChildrenChanged: console.log(`children changed; now have: ${children.length}`)
                onChildrenRectChanged: console.log(`children rect changed`)
            }
    
            Label {
                id: hammerLabel
                anchors.horizontalCenter: parent.horizontalCenter
                y: 120
                text: qsTr("🔨 Hammer")
                font.bold: true
                opacity: 0.6
                font.pointSize: 36
                font.family: "Apple Color Emoji"
                visible: textArea.state === "MINIMAL"
            }
    
            Row {
                id: loadResourcesRow
                y: hammerLabel.y + 80
                anchors.horizontalCenter: parent.horizontalCenter
                spacing: 10
    
                Button {
                    id: loadResourceButton
                    text: qsTr("Button")
                    visible: textArea.state === "MINIMAL"
                }
    
                TextArea {
                    id: textArea
                    placeholderText: qsTr("or load it here")
                    renderType: Text.NativeRendering
                    // ensure the tooltip isn't monospace, only the text
                    font.family: text ? "Ubuntu Mono" : "Ubuntu"
                    selectByMouse: true
                    wrapMode: "WrapAtWordBoundaryOrAnywhere"
    
                    // ensure focus remains when the area is reparented
                    onWidthChanged: textArea.forceActiveFocus()
                    // it doesn't have focus on startup
                    Component.onCompleted: textArea.focus = false
    
                    states: [
                        State {
                            name: "MINIMAL"; when: !textArea.text
                            ParentChange {
                                target: textArea
                                parent: loadResourcesRow
                                width: 300
                                height: undefined
                            }
                        },
                        State {
                            name: "EXPANDED"; when: textArea.text
                            ParentChange {
                                target: textArea
                                parent: addResourceScrollView
                                x: 0; y: 0
                                width: window.width
                                height: window.height
                            }
                        }
                    ]
                    state: "MINIMAL"
    
                    transitions: Transition {
                        ParentAnimation {
                            NumberAnimation { properties: "x,y,width,height";  easing.type: Easing.InCubic; duration: 600 }
                        }
                    }
                }
    
            }
    
            Text {
                id: experimentalText
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.verticalCenter: parent.verticalCenter
                text: qsTr("Experimental")
                enabled: false
                z: 0
                rotation: -45
                opacity: 0.1
                font.pixelSize: 96
            }
    
        }
    
        RowLayout {
            id: buttonsRow
            x: 0
            y: parent.height - height
            width: window.width
    
            Button {
                id: settingsButton
                text: "☰"
    
                onClicked: addResourcesPage.state = "EDITING_SETTINGS"
            }
    
            Button {
                id: actionButton
                text: "stuff"
                visible: textArea.text || addResourcesPage.state === "EDITING_SETTINGS"
                Layout.fillWidth: true
            }
        }
    }
    

    I suspect ParentChange { width: window.width; height: window.height } is at fault here - I've played around with a lot of values there + in the ScrollView but nothing is working.

    1 Reply Last reply
    0
    • GrecKoG Offline
      GrecKoG Offline
      GrecKo
      Qt Champions 2018
      wrote on last edited by
      #2

      Do this :

      State {
          name: "EXPANDED"; when: textArea.text
          ParentChange {
              target: textArea
              parent: addResourceScrollView.contentItem.contentItem
              x: 0; y: 0
              width: window.width
          }
      }
      

      You don't need to set the height since you don't want it to be constrained.

      As for parent: addResourceScrollView.contentItem.contentItem:
      addResourceScrollView.contentItem is the default Flickable of the ScrollView, and you want to put your TextArea in the contentItem of the Flickable. Personnaly I would have directly used a Flickable instead.

      1 Reply Last reply
      2
      • V Offline
        V Offline
        Vadi2
        wrote on last edited by
        #3

        Aha, thanks,I would have never thought of using that parent. I'll read up on Flickable, I've been ignoring it because I focus on desktop platforms.

        ScrollView now scrolls as it should, however reverting to the previous state does not go exactly to plan:

        0_1558614347668_Peek 2019-05-23 14-24.gif

        What would be the issue? I'm at a loss.

        1 Reply Last reply
        0
        • Shrinidhi UpadhyayaS Offline
          Shrinidhi UpadhyayaS Offline
          Shrinidhi Upadhyaya
          wrote on last edited by
          #4

          Hi @Vadi2 , it seems to be working fine in my case, have made any changes to the code which you had posted?

          Shrinidhi Upadhyaya.
          Upvote the answer(s) that helped you to solve the issue.

          1 Reply Last reply
          0
          • V Offline
            V Offline
            Vadi2
            wrote on last edited by
            #5

            No, not at all! I've just double-checked by taking the above .qml and replacing the single State within it. Same issue as in the gif, using Qt 5.12.2.

            1 Reply Last reply
            0
            • Pradeep P NP Offline
              Pradeep P NP Offline
              Pradeep P N
              wrote on last edited by Pradeep P N
              #6

              Hi @Vadi2
              Your code works fine.

              I just changed the state of TextArea to test on button click to

              Button {
                          id: settingsButton
                          text: "☰"
              
                          onClicked: {
                              textArea.state = "MINIMAL"
                              addResourcesPage.state = "EDITING_SETTINGS"
                          }
                      }
              

              And the contents are back to their original places.
              0_1558673206248_14a0953b-3fb4-443f-bd29-75086d3404d7-image.png

              Pradeep Nimbalkar.
              Upvote the answer(s) that helped you to solve the issue...
              Keep code clean.

              1 Reply Last reply
              0
              • V Offline
                V Offline
                Vadi2
                wrote on last edited by
                #7

                No luck still, somehow! I'm confused.

                0_1558674547397_Peek 2019-05-24 07-08.gif

                Pradeep P NP 1 Reply Last reply
                0
                • Shrinidhi UpadhyayaS Offline
                  Shrinidhi UpadhyayaS Offline
                  Shrinidhi Upadhyaya
                  wrote on last edited by
                  #8

                  Hi @Vadi2 , can you share your latest complete code, because for me its working fine.

                  Shrinidhi Upadhyaya.
                  Upvote the answer(s) that helped you to solve the issue.

                  1 Reply Last reply
                  1
                  • V Offline
                    V Offline
                    Vadi2
                    wrote on last edited by
                    #9

                    Here it is: https://transfer.sh/F5ceH/dodgy-scrollview.zip

                    1 Reply Last reply
                    0
                    • V Vadi2

                      No luck still, somehow! I'm confused.

                      0_1558674547397_Peek 2019-05-24 07-08.gif

                      Pradeep P NP Offline
                      Pradeep P NP Offline
                      Pradeep P N
                      wrote on last edited by
                      #10

                      @Vadi2 can you try it with Button click as i tested ?
                      its fine on Windows & Qt 5.12.2

                      Pradeep Nimbalkar.
                      Upvote the answer(s) that helped you to solve the issue...
                      Keep code clean.

                      1 Reply Last reply
                      0
                      • V Offline
                        V Offline
                        Vadi2
                        wrote on last edited by
                        #11

                        Yes, the latest gif was with the button click. I'll test the qml file on Windows as well, just to be sure...

                        1 Reply Last reply
                        0
                        • Pradeep P NP Offline
                          Pradeep P NP Offline
                          Pradeep P N
                          wrote on last edited by Pradeep P N
                          #12

                          0_1558677270584_Peek 2019-05-24 11-23.gif

                          Your code only from the above post.

                          Pradeep Nimbalkar.
                          Upvote the answer(s) that helped you to solve the issue...
                          Keep code clean.

                          1 Reply Last reply
                          0
                          • V Offline
                            V Offline
                            Vadi2
                            wrote on last edited by
                            #13

                            Windows has the same result :(

                            0_1558677854783_Peek 2019-05-24 07-53.gif

                            1 Reply Last reply
                            0
                            • Shrinidhi UpadhyayaS Offline
                              Shrinidhi UpadhyayaS Offline
                              Shrinidhi Upadhyaya
                              wrote on last edited by Shrinidhi Upadhyaya
                              #14

                              Hi @Vadi2 , you need to specify height and width to the Row.

                              I have specified this and it works fine for me:-

                              width: hammerLabel.width
                              height: hammerLabel.height
                              

                              And one more suggestion, when you enter the text you reparent it to the ScrollView and once it gets reparented to the ScrollView you need to again click on the TextArea to edit the Text, if you want to continue to edit the TextArea even when you reparent it , you can use the onParentChanged signal. So instead of using onWidthChanged, you can use onParentChanged like this:

                              onParentChanged: textArea.forceActiveFocus()
                              

                              Shrinidhi Upadhyaya.
                              Upvote the answer(s) that helped you to solve the issue.

                              Pradeep P NP 1 Reply Last reply
                              3
                              • Shrinidhi UpadhyayaS Shrinidhi Upadhyaya

                                Hi @Vadi2 , you need to specify height and width to the Row.

                                I have specified this and it works fine for me:-

                                width: hammerLabel.width
                                height: hammerLabel.height
                                

                                And one more suggestion, when you enter the text you reparent it to the ScrollView and once it gets reparented to the ScrollView you need to again click on the TextArea to edit the Text, if you want to continue to edit the TextArea even when you reparent it , you can use the onParentChanged signal. So instead of using onWidthChanged, you can use onParentChanged like this:

                                onParentChanged: textArea.forceActiveFocus()
                                
                                Pradeep P NP Offline
                                Pradeep P NP Offline
                                Pradeep P N
                                wrote on last edited by
                                #15

                                @Shrinidhi-Upadhyaya Cool.
                                @Vadi2 Try this.

                                Pradeep Nimbalkar.
                                Upvote the answer(s) that helped you to solve the issue...
                                Keep code clean.

                                1 Reply Last reply
                                1
                                • V Offline
                                  V Offline
                                  Vadi2
                                  wrote on last edited by
                                  #16

                                  Hm, it kind of works - but I want the Row to auto-size the the contents of its children, I don't want to force it into an explicit width/height.

                                  Also the TextArea seems to lose it's border? You can see it in https://ddgobkiprc33d.cloudfront.net/8b195d8c-bd58-4dc1-ba36-9c3a10e7aba2.png :(

                                  Thanks for all the help so far, really appreciate it.

                                  1 Reply Last reply
                                  0
                                  • Pradeep P NP Offline
                                    Pradeep P NP Offline
                                    Pradeep P N
                                    wrote on last edited by Pradeep P N
                                    #17

                                    Hi @Vadi2

                                    Is this what you expected ?

                                    0_1558689491473_Test.gif

                                    Pradeep Nimbalkar.
                                    Upvote the answer(s) that helped you to solve the issue...
                                    Keep code clean.

                                    1 Reply Last reply
                                    2
                                    • V Offline
                                      V Offline
                                      Vadi2
                                      wrote on last edited by
                                      #18

                                      So close!

                                      The textArea's height would be window.height - buttonsRow.height - that is, not overlap the buttons below. It should also only resize on the presence of text, not via the ☰ button (it's actually a settings button).

                                      How did you manage to get it to size back down okay?

                                      Pradeep P NP 2 Replies Last reply
                                      0
                                      • Shrinidhi UpadhyayaS Offline
                                        Shrinidhi UpadhyayaS Offline
                                        Shrinidhi Upadhyaya
                                        wrote on last edited by
                                        #19

                                        Hi @Vadi2 , i guess there is some problem with ScrollView.

                                        1. Problem 1 (Sample Code)

                                        TextArea {
                                                        id: textArea
                                        
                                                        height: 100
                                                        width: 100
                                                        anchors.left: view.right
                                                        anchors.leftMargin: 100
                                                    }
                                        
                                                    ScrollView {
                                                        id: view
                                        
                                                        height: 100
                                                        width: 100
                                                        clip: true
                                        
                                                        TextArea {
                                                            id: textArea1
                                        
                                                            width: parent.width
                                                            //####Uncomment the below line the,there will be no border line
                                                            wrapMode: "WrapAtWordBoundaryOrAnywhere"
                                                        }
                                                    }
                                        

                                        I dont knoe how but TextArea inside the ScrolllView behaves weird, if you set wrapMode property, the border does not appear, but if dont set it ,border appears but does not take width specified.

                                        2. Problem 2 (Sample Code)

                                        ScrollView {
                                                id: view
                                        
                                                height: 100
                                                width: 100
                                                clip: true
                                            }
                                        
                                            Rectangle {
                                                id: redRect
                                        
                                                height: 100
                                                width: 100
                                                color: "transparent"
                                                border.color: "red"
                                                anchors.centerIn: parent
                                        
                                                TextArea {
                                                    id: textArea
                                        
                                                    width: parent.width
                                                    parent: text
                                                            ? view.contentItem.contentItem
                                                            : redRect
                                        
                                                    onParentChanged: {
                                                        textArea.forceActiveFocus()
                                                    }
                                                }
                                            }
                                        

                                        here if you enter the text , you will see that TextArea changes its parent to ScrollView,after that if you delete the text,it should come back to Rectangle, but you will see that borderLine of TextArea remains in the ScrollView,but the text comes back to Rectangle(Weird)

                                        So as @GrecKo suggested the best solution would be to use Flickable:-

                                        Here is the sample code:-

                                        Flickable {
                                                        id: view
                                        
                                                        height: 100
                                                        width: 200
                                                        clip: true
                                                        flickableDirection: Flickable.VerticalFlick
                                                        contentHeight: textArea.contentHeight
                                                        contentWidth: 200
                                                    }
                                        
                                                    Rectangle {
                                                        id: redRect
                                        
                                                        height: 100
                                                        width: 100
                                                        color: "red"
                                                        anchors.centerIn: parent
                                        
                                                        TextArea {
                                                            id: textArea
                                        
                                                            width: parent.width
                                                            wrapMode: "WrapAtWordBoundaryOrAnywhere"
                                                            anchors.centerIn: parent
                                                            parent: text?view.contentItem:redRect
                                                        }
                                                    }
                                        

                                        Shrinidhi Upadhyaya.
                                        Upvote the answer(s) that helped you to solve the issue.

                                        1 Reply Last reply
                                        3
                                        • V Vadi2

                                          So close!

                                          The textArea's height would be window.height - buttonsRow.height - that is, not overlap the buttons below. It should also only resize on the presence of text, not via the ☰ button (it's actually a settings button).

                                          How did you manage to get it to size back down okay?

                                          Pradeep P NP Offline
                                          Pradeep P NP Offline
                                          Pradeep P N
                                          wrote on last edited by Pradeep P N
                                          #20

                                          @Vadi2
                                          Yes, Height should be window height - row height from which you can avoid the overlap.

                                          Just remove the

                                          textArea.state = "MINIMAL"
                                          

                                          from Button clicked to avoid the behavior (I did just to test the code)

                                          I Used the Flickable { } in place of ScrollView {}. If you want the ScrollBar you can add it to the Flickable {}

                                          Also now parent will change as its Flickable {} directly

                                          State {
                                                                  name: "EXPANDED"; when: textArea.text
                                                                  ParentChange {
                                                                      target: textArea
                                                                      parent: addResourceScrollView.contentItem
                                                                      x: 0; y: 0
                                                                      width: window.width
                                                                      height: window.height
                                                                  }
                                                              }
                                          

                                          And also in this case you don't have to set the width & height for the Row {}

                                          Pradeep Nimbalkar.
                                          Upvote the answer(s) that helped you to solve the issue...
                                          Keep code clean.

                                          1 Reply Last reply
                                          2

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved