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. QML SplitView - handleDelegate

QML SplitView - handleDelegate

Scheduled Pinned Locked Moved Solved QML and Qt Quick
14 Posts 2 Posters 7.2k 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.
  • P Offline
    P Offline
    peteritv
    wrote on last edited by
    #1

    Hi all!

    I use a horizontal SplitView in QML with 2 children (let's say: Rectangles).
    When the SplitView handle is dragged, I want to calculate the left/right ratio and save the value for further processing (store it in settings or so).

    The documentation (http://doc.qt.io/qt-5/qml-qtquick-controls-splitview.html#details) mentions something like "handleDelegate Component" which seems to be of some use, but it only mentions readonly properties. Is it so that the delegate will be activated on any SplitView event, and I use the properties to find out what exactly happened?

    The editor also suggests the existance of an event called "on__HandlesChanged: ". Maybe that is the way to go?

    Does anyone know how to implement such a thing?
    Maybe some example?

    T.I.A!

    1 Reply Last reply
    0
    • p3c0P Offline
      p3c0P Offline
      p3c0
      Moderators
      wrote on last edited by
      #2

      @peteritv

      Is it so that the delegate will be activated on any SplitView event, and I use the properties to find out what exactly happened?

      There is already a default one activated i.e the thin vertical 1 width line which you click and drag.
      You can override it and create new one as:

      handleDelegate: Rectangle {
          width: 20
          color: "red"
      }
      

      The editor also suggests the existance of an event called "on__HandlesChanged: ". Maybe that is the way to go?

      Not sure. This is a private property and may change in future and so cant be relied on.

      Does anyone know how to implement such a thing?

      When the handle is moved the items which it holds are resized too. So you can monitor these size change in your Rectangles ?

      157

      1 Reply Last reply
      0
      • P Offline
        P Offline
        peteritv
        wrote on last edited by
        #3

        @p3c0 : Thanx for your reply!

        Now I know how that delegate works :)

        But now for the resizing stuff, this is my simplified QML so far:

        Item {
            id: mainItem
            anchors.fill: parent
        
            SplitView {
                id: splitMain
                orientation: Qt.Horizontal
                anchors.fill: parent
                property var ratio: [ 0.6, 0.4 ]
                Rectangle { width: splitMain.width * splitMain.ratio[0] }
                Rectangle { width: splitMain.width * splitMain.ratio[1] }
                handleDelegate: Rectangle { width: 4; color: "red" }
            }
        }
        

        I gave the splitview a dynamic property "ratio" which is used to calculate the width of children. Children will be created dynamiccally later on, so this code just illustrates.

        Point is that the width of a child is calculated from ratio, so using a child event to change the ratio will cause a circular reference, right?

        So I need some kind of event at the splitMain level that signals the user is fiddling with the handles. I tried onChildrenChanged and onChildrenRectChanged, but those do not seem to be fired.

        To indicate what I want, I tried the child.onWidthChanged anyway, and surprisingly it kinda works, besides the fact that the first initialization immediately resets ratio to 0.

        Item {
            id: mainItem
            anchors.fill: parent
        
            SplitView {
                id: splitMain
                orientation: Qt.Horizontal
                anchors.fill: parent
                property var ratio: [ 0.6, 0.4 ]
        
                Rectangle {
                    id: r1
                    width: splitMain.width * splitMain.ratio[0];
                    Text { text: splitMain.ratio[0] }
                    onWidthChanged: {
                        if (splitMain.resizing ) splitMain.ratioChanged()
                    }
                }
                Rectangle {
                    id: r2
                    width: splitMain.width * splitMain.ratio[1];
                    Text { text: splitMain.ratio[1] }
                }
                handleDelegate: Rectangle { width: 4; color: "red" }
        
                onRatioChanged: {
                    ratio[0] = r1.width / width
                    ratio[1] = (r2.width + 4) / width
                }
            }
        }
        

        Any ideas on how to fix this?

        1 Reply Last reply
        0
        • P Offline
          P Offline
          peteritv
          wrote on last edited by
          #4

          A few hours later, and after a lot of trial & error, I came up with this result, that is supposed to work for both horizontal as vertical SplitView, and with just 2 children:

          import QtQuick 2.6
          import QtQuick.Controls 1.5
          import QtQuick.Layouts 1.3
          
          Item {
              id: mainItem
              anchors.fill: parent
          
              SplitView {
                  id: splitMain
                  orientation: Qt.Vertical
                  anchors.fill: parent
                  signal handleChanged()
                  property real ratio: 0.6
          
                  Rectangle {
                      id: r1
                      width: if (splitMain.orientation == Qt.Horizontal) {
                                 splitMain.width * splitMain.ratio
                             }
                      height: if (splitMain.orientation == Qt.Vertical) {
                                  splitMain.height * splitMain.ratio
                              }
                      Text { text: splitMain.ratio.toFixed(2) }
                      onWidthChanged: {
                          if ( (splitMain.orientation == Qt.Horizontal) && splitMain.resizing )
                              splitMain.handleChanged()
                      }
                      onHeightChanged: {
                          if ( (splitMain.orientation == Qt.Vertical) && splitMain.resizing )
                              splitMain.handleChanged()
                      }
                  }
                  Rectangle {
                      id: r2
                      Layout.fillWidth: true
                      Layout.fillHeight: true
                  }
                  handleDelegate: Rectangle {
                      width: (splitMain.orientation == Qt.Horizontal) ? 4 : 0
                      height: (splitMain.orientation == Qt.Vertical) ? 4 : 0
                      color: "red"
                  }
          
                  onHandleChanged: {
                      ratio = (splitMain.orientation == Qt.Horizontal) ? r1.width / width : r1.height / height
                      console.log("handle changed to ratio " + ratio.toFixed(2))
                  }
              }
          }
          

          As you can see, I declared an event "handleChanged" that is triggered when width/height (depending on SplitView orientation) of the children changes.

          Now I am 95% happy!
          In horizontal orientation this works like a charm, but when changed to vertical (splitMain.orientation = Qt.Vertical) somehow the initial ratio get's lost?

          Please???? Any help will be GREATLY appreciated!

          1 Reply Last reply
          0
          • P Offline
            P Offline
            peteritv
            wrote on last edited by
            #5

            OK, I dug a little deeper into the problem with this code:

            Item {
                id: mainItem
                anchors.fill: parent
            
                SplitView {
                    id: splitMain
                    orientation: Qt.Horizontal
                    anchors.fill: parent
                    signal handleChanged
                    property real ratio: 0.6
            
                    Rectangle {
                        id: r1
                        width: {
                            if (splitMain.orientation == Qt.Horizontal) {
                                console.log("width: " + splitMain.width)
                                return splitMain.width * splitMain.ratio
                            }
                        }
                        height: {
                            if (splitMain.orientation == Qt.Vertical) {
                                console.log("height: " + splitMain.height)
                                return splitMain.height * splitMain.ratio
                            }
                        }
                        Text {
                            text: splitMain.ratio.toFixed(2)
                        }
                        onWidthChanged: {
                            if ((splitMain.orientation == Qt.Horizontal)
                                    && splitMain.resizing)
                                splitMain.handleChanged()
                        }
                        onHeightChanged: {
                            if ((splitMain.orientation == Qt.Vertical)
                                    && splitMain.resizing)
                                splitMain.handleChanged()
                        }
                    }
                    Rectangle {
                        id: r2
                        Layout.fillWidth: if (splitMain.orientation == Qt.Horizontal)
                                              true
                        Layout.fillHeight: if (splitMain.orientation == Qt.Vertical)
                                               true
                    }
                    handleDelegate: Rectangle {
                        width: (splitMain.orientation == Qt.Horizontal) ? 4 : 0
                        height: (splitMain.orientation == Qt.Vertical) ? 4 : 0
                        color: "red"
                    }
            
                    onHandleChanged: {
                        ratio = (splitMain.orientation == Qt.Horizontal) ? r1.width / width : r1.height / height
                        console.log("handle changed to ratio " + ratio.toFixed(2))
                    }
                }
            }
            

            Now on horizontal orientation, I get this output after initialization:

            Starting /home/peter/V-PlaySDK/5.7/gcc_64/bin/qmlscene...
            qml: width: 0
            file:///home/peter/Projects/BridgeComponents/MainForm.ui.qml:48:32: Unable to assign [undefined] to bool
            qml: width: 800
            

            On vertical orientation I get this:

            Starting /home/peter/V-PlaySDK/5.7/gcc_64/bin/qmlscene...
            qml: height: 0
            qml: height: -21
            file:///home/peter/Projects/BridgeComponents/MainForm.ui.qml:46:31: Unable to assign [undefined] to bool
            

            and then it stops...

            Now I start to think there is more to this problem than meets the eye, so here is my main QML:

            import QtQuick 2.6
            import QtQuick.Controls 1.5
            
            ApplicationWindow {
                visible: true
                width: 800
                height: 600
                title: qsTr("Bridge layout")
            
                menuBar: MenuBar {
                    Menu {
                        title: qsTr("File")
                        MenuItem {
                            text: qsTr("&Open")
                            onTriggered: console.log("Open action triggered");
                        }
                        MenuItem {
                            text: qsTr("Exit")
                            onTriggered: Qt.quit();
                        }
                    }
                }
            
                MainForm {
                    anchors.fill: parent
                }
            }
            

            Now does that not CLEARLY state that the default height is 600?

            So how come the default width is being handled OK, but the height not?

            And both (horizontal and vertical) complain about "Unable to assign [undefined] to bool"? What is that about?

            1 Reply Last reply
            0
            • P Offline
              P Offline
              peteritv
              wrote on last edited by
              #6

              AAAAAHHHHHHH!!!!!!!!!!

              I removed the menuBar from the main QML, and now IT IS WORKING!!!

              Is this a BUG or am I just newbie enough to not understand?

              1 Reply Last reply
              0
              • P Offline
                P Offline
                peteritv
                wrote on last edited by
                #7

                There is still the matter of the "Unable to assign [undefined] to bool" though...

                Any suggestions?

                1 Reply Last reply
                0
                • P Offline
                  P Offline
                  peteritv
                  wrote on last edited by
                  #8

                  OK, solved that too!

                  Layout.fillWidth and Layout.fillHeight do not like to be unassigned when you call on them, so this code solves that problem:

                          Rectangle {
                              id: r2
                              Layout.fillWidth: (splitMain.orientation == Qt.Horizontal) ? true : false
                              Layout.fillHeight: (splitMain.orientation == Qt.Vertical) ? true : false
                          }
                  

                  I guess I am happy now!

                  But I am not closing this topic yet, because the main reason why I started this topic was:

                  When you DO NOT touch the SplitView handle, and you resize the Window, then the SplitView resizes with it, keeping initial aspect ratio. However, when u touch the handle, all bets or off and resizing the Window does no longer keep aspect ratio.

                  Now I am sure there are some real QML guru's out there that can explain?

                  Greetz,
                  Peter

                  1 Reply Last reply
                  0
                  • P Offline
                    P Offline
                    peteritv
                    wrote on last edited by peteritv
                    #9

                    Should I make that a new Topic?

                    I already had a topic for that, but deleted it now, due to new knowledge :)

                    So how to resize the SplitView when the handle has been touched, and the container resizes?

                    1 Reply Last reply
                    0
                    • P Offline
                      P Offline
                      peteritv
                      wrote on last edited by
                      #10

                      BTW: I think that Layout.fillWidth and Layout.fillHeight should BOTH accept "undefined", and keep their current value, or is it just me who thinks so?

                      1 Reply Last reply
                      0
                      • P Offline
                        P Offline
                        peteritv
                        wrote on last edited by
                        #11

                        The higher layer programming languages get, the more things are being taken for granted! I still dream of the times that every bit and byte had to be accounted for when programming in direct machine language :)

                        1 Reply Last reply
                        0
                        • P Offline
                          P Offline
                          peteritv
                          wrote on last edited by
                          #12

                          Maybe I can get a vote here?

                          Who thinks Layout.fillWidth and Layout.fillHeight should accept "undefined" and keep there current value?

                          1 Reply Last reply
                          0
                          • P Offline
                            P Offline
                            peteritv
                            wrote on last edited by
                            #13

                            Vote + if you agree, vote - otherwise...

                            1 Reply Last reply
                            0
                            • P Offline
                              P Offline
                              peteritv
                              wrote on last edited by
                              #14

                              I'll continue this on a new Topic...

                              This topic has reached its goal, and so I will will mark it is such.

                              1 Reply Last reply
                              0

                              • Login

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