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. Dockable window implementation in qml
QtWS25 Last Chance

Dockable window implementation in qml

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
3 Posts 2 Posters 1.1k 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.
  • K Offline
    K Offline
    kaushikv
    wrote on last edited by kaushikv
    #1

    Hi,

    I am trying to create a dock able window in qml , it kind of works partially correct but when i first undock it by dragging the window, it does not place the window at the mouse pointer i am not able to understand what i am doing wrong?

    can anyone help me in fixing it ?

    here is my code :

    import QtQuick
    import QtQuick.Controls
    import QtQuick.Window
    import QtQuick.Controls.Material
    
    Item {
        id: root
        default property alias contents: placeholder.data
        property alias title: titleLabel.text
        implicitHeight: mainWindow.height - statusBar.height - 15
        
        Rectangle {
            
            id: content
            anchors.fill: parent
            height: implicitHeight
            state: "docked"
            border.color: "slategrey"
            border.width: 1
            ToolBar {
                id: toolBar
                implicitHeight: 30
                Material.foreground: "white"
                Material.background: "#dcdcdc"
                anchors { top: parent.top; left: parent.left; right: parent.right }
                Label {
                    id: titleLabel
                    color: "black"
                    anchors { left: parent.left; leftMargin: 8; verticalCenter: parent.verticalCenter }
                }
                
                MouseArea {
                    id: dragMouseArea
                    anchors.fill: parent
                    hoverEnabled: false
                    acceptedButtons: Qt.LeftButton | Qt.RightButton
                    propagateComposedEvents: true
                    property variant clickPos: "1,1"
                    /*onPressed: (mouse) => {
                                   clickPos = Qt.point(mouse.x,mouse.y)
                                   if (content.state === "docked") {
                                        let globalMousePos = mapToGlobal(Qt.point(mouse.x, mouse.y));
         var new_x = globalMousePos.x;
         var new_y = globalMousePos.y;
       let relativePosW = mapToItem(undockedContainer, Qt.point(mouse.x, mouse.y));
               window.x = new_x ;
               window.y = new_y 
                                       // Set the initial position of the window when undocked
                                       //window.x = new_x
                                       //window.y = new_y
                                   }
                               }*/
                    
                    /*onPositionChanged:  (mouse) => {
                                            var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
                                            var new_x = window.x + delta.x
                                            var new_y = window.y + delta.y
                                            
                                            if (content.state === "docked") {
                                                // Check if the mouse is outside the bounds of the docked area
                                                if (mouse.y < toolBar.height || mouse.x < 0 || mouse.x > parent.width) {
                                                    content.state = "undocked"
                                                    // Move the window to the mouse position
                                                    window.x = new_x
                                                    window.y = new_y
                                                }
                                            } else {
                                                // Get the maximum x and y positions for the undocked window
                                                var max_x = Screen.desktopAvailableWidth - window.width
                                                var max_y = Screen.desktopAvailableHeight - window.height
                                                
                                                // Update the window position, making sure it stays within the screen bounds
                                                if (new_x < 0) new_x = 0
                                                if (new_x > max_x) new_x = max_x
                                                if (new_y < 0) new_y = 0
                                                if (new_y > max_y) new_y = max_y
                                                
                                                window.x = new_x
                                                window.y = new_y
                                            }
                                        }*/
                    
                    property point relativePos;
    
                    onPositionChanged:  (mouse) => {
                                            // get the mouse pos in screen coordinates
                                            let globalMousePos = mapToGlobal(Qt.point(mouse.x, mouse.y));
                                            var new_x = globalMousePos.x;
                                            var new_y = globalMousePos.y;
                                            
                                            if (content.state === "docked") {
                                                // Check if the mouse is outside the bounds of the docked area
                                                if (mouse.y < toolBar.height || mouse.x < 0 || mouse.x > parent.width) {
                                                    console.log("Initial window position: " + new_x + " " + new_y);
                                                    content.state = "undocked"
                                                    //  store the click point where the drag started
                                                    relativePos = mapToItem(toolBar, Qt.point(mouse.x, mouse.y));
                                                    
                                                    console.log("relativePos window position: " + relativePos.x + " " + relativePos.y);
                                                    window.x = new_x - relativePos.x ;
                                                    window.y = new_y - relativePos.y ;
                                           
                                                }
                                            } else {
                                                console.log("Move the window to the mouse position: " + new_x + " " + new_y);
                                                window.x = Math.max(0,
                                                                    Math.min(new_x - relativePos.x, Screen.desktopAvailableWidth - window.width));
                                                window.y = Math.max(0, Math.min(new_y - relativePos.y, Screen.desktopAvailableHeight - window.height));
                                            }
                                            
                                        }
    
    
                    onClicked: (mouse) => {
                                   if (mouse.button === Qt.RightButton)
                                   contextMenu.popup()
                               }
                    
                    //Adding a right click menu as well
                    Menu {
                        id: contextMenu
                        spacing: 0
                        MenuItem { id: dockMenu; text: "Dock"; onClicked: content.state = "docked"; implicitHeight: 30}
                        MenuItem { id: unDockMenu; text: "Float"; onClicked: content.state = "undocked" ; implicitHeight: 30}
                    }
                    
                    //Adding a button on the right corder, to give users some hint on docking/undocking, since right click is not that obvious
                    Row {
                        anchors { right: parent.right; verticalCenter: parent.verticalCenter;  }
                        Button {
                            icon.source: "inverted-triangle.svg"
                            flat: true
                            width: 20
                            Material.foreground: "black"
                            text:  qsTr("▶"); rotation: 90 //Preferred would be show an image here
                            onClicked: {
                                contextMenu.popup()
                            }
                        }
                    }
                }
            }
            Item {
                id: placeholder
                anchors { top: toolBar.bottom; left: parent.left; right: parent.right; bottom: parent.bottom }
            }
            states: [
                State {
                    name: "undocked"
                    PropertyChanges { target: root; height: 0 }
                    PropertyChanges { target: window; visible: true }
                    ParentChange { target: content; parent: undockedContainer }
                    //PropertyChanges { target: window; visible: true; x: 250; y: 250 }
                    //this is to make sure the width becomes zero and rest of the control takes the realstate
                    PropertyChanges {target: navigationWindow; width: 0 }
                    PropertyChanges {target: toolBar; Material.background: "#f0e68c" }
                    PropertyChanges {target: unDockMenu; enabled: false }
                    PropertyChanges {target: dockMenu; enabled: true }
                },
                State {
                    name: "docked"
                    PropertyChanges { target: root; height: implicitHeight }
                    PropertyChanges { target: window; visible: false }
                    ParentChange { target: content; parent: root }
                    PropertyChanges {target: unDockMenu; enabled: true }
                    PropertyChanges {target: dockMenu; enabled: false }
                }
            ]
        }
        Window {
            id: window
            width: 250;
            height: 700;
            
            flags: Qt.FramelessWindowHint
            
            Item {
                id: undockedContainer
                anchors.fill: parent           
            }
            
            onClosing: {
                content.state = "docked"
            }
        }
    }
    
    K 1 Reply Last reply
    0
    • K kaushikv

      Hi,

      I am trying to create a dock able window in qml , it kind of works partially correct but when i first undock it by dragging the window, it does not place the window at the mouse pointer i am not able to understand what i am doing wrong?

      can anyone help me in fixing it ?

      here is my code :

      import QtQuick
      import QtQuick.Controls
      import QtQuick.Window
      import QtQuick.Controls.Material
      
      Item {
          id: root
          default property alias contents: placeholder.data
          property alias title: titleLabel.text
          implicitHeight: mainWindow.height - statusBar.height - 15
          
          Rectangle {
              
              id: content
              anchors.fill: parent
              height: implicitHeight
              state: "docked"
              border.color: "slategrey"
              border.width: 1
              ToolBar {
                  id: toolBar
                  implicitHeight: 30
                  Material.foreground: "white"
                  Material.background: "#dcdcdc"
                  anchors { top: parent.top; left: parent.left; right: parent.right }
                  Label {
                      id: titleLabel
                      color: "black"
                      anchors { left: parent.left; leftMargin: 8; verticalCenter: parent.verticalCenter }
                  }
                  
                  MouseArea {
                      id: dragMouseArea
                      anchors.fill: parent
                      hoverEnabled: false
                      acceptedButtons: Qt.LeftButton | Qt.RightButton
                      propagateComposedEvents: true
                      property variant clickPos: "1,1"
                      /*onPressed: (mouse) => {
                                     clickPos = Qt.point(mouse.x,mouse.y)
                                     if (content.state === "docked") {
                                          let globalMousePos = mapToGlobal(Qt.point(mouse.x, mouse.y));
           var new_x = globalMousePos.x;
           var new_y = globalMousePos.y;
         let relativePosW = mapToItem(undockedContainer, Qt.point(mouse.x, mouse.y));
                 window.x = new_x ;
                 window.y = new_y 
                                         // Set the initial position of the window when undocked
                                         //window.x = new_x
                                         //window.y = new_y
                                     }
                                 }*/
                      
                      /*onPositionChanged:  (mouse) => {
                                              var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
                                              var new_x = window.x + delta.x
                                              var new_y = window.y + delta.y
                                              
                                              if (content.state === "docked") {
                                                  // Check if the mouse is outside the bounds of the docked area
                                                  if (mouse.y < toolBar.height || mouse.x < 0 || mouse.x > parent.width) {
                                                      content.state = "undocked"
                                                      // Move the window to the mouse position
                                                      window.x = new_x
                                                      window.y = new_y
                                                  }
                                              } else {
                                                  // Get the maximum x and y positions for the undocked window
                                                  var max_x = Screen.desktopAvailableWidth - window.width
                                                  var max_y = Screen.desktopAvailableHeight - window.height
                                                  
                                                  // Update the window position, making sure it stays within the screen bounds
                                                  if (new_x < 0) new_x = 0
                                                  if (new_x > max_x) new_x = max_x
                                                  if (new_y < 0) new_y = 0
                                                  if (new_y > max_y) new_y = max_y
                                                  
                                                  window.x = new_x
                                                  window.y = new_y
                                              }
                                          }*/
                      
                      property point relativePos;
      
                      onPositionChanged:  (mouse) => {
                                              // get the mouse pos in screen coordinates
                                              let globalMousePos = mapToGlobal(Qt.point(mouse.x, mouse.y));
                                              var new_x = globalMousePos.x;
                                              var new_y = globalMousePos.y;
                                              
                                              if (content.state === "docked") {
                                                  // Check if the mouse is outside the bounds of the docked area
                                                  if (mouse.y < toolBar.height || mouse.x < 0 || mouse.x > parent.width) {
                                                      console.log("Initial window position: " + new_x + " " + new_y);
                                                      content.state = "undocked"
                                                      //  store the click point where the drag started
                                                      relativePos = mapToItem(toolBar, Qt.point(mouse.x, mouse.y));
                                                      
                                                      console.log("relativePos window position: " + relativePos.x + " " + relativePos.y);
                                                      window.x = new_x - relativePos.x ;
                                                      window.y = new_y - relativePos.y ;
                                             
                                                  }
                                              } else {
                                                  console.log("Move the window to the mouse position: " + new_x + " " + new_y);
                                                  window.x = Math.max(0,
                                                                      Math.min(new_x - relativePos.x, Screen.desktopAvailableWidth - window.width));
                                                  window.y = Math.max(0, Math.min(new_y - relativePos.y, Screen.desktopAvailableHeight - window.height));
                                              }
                                              
                                          }
      
      
                      onClicked: (mouse) => {
                                     if (mouse.button === Qt.RightButton)
                                     contextMenu.popup()
                                 }
                      
                      //Adding a right click menu as well
                      Menu {
                          id: contextMenu
                          spacing: 0
                          MenuItem { id: dockMenu; text: "Dock"; onClicked: content.state = "docked"; implicitHeight: 30}
                          MenuItem { id: unDockMenu; text: "Float"; onClicked: content.state = "undocked" ; implicitHeight: 30}
                      }
                      
                      //Adding a button on the right corder, to give users some hint on docking/undocking, since right click is not that obvious
                      Row {
                          anchors { right: parent.right; verticalCenter: parent.verticalCenter;  }
                          Button {
                              icon.source: "inverted-triangle.svg"
                              flat: true
                              width: 20
                              Material.foreground: "black"
                              text:  qsTr("▶"); rotation: 90 //Preferred would be show an image here
                              onClicked: {
                                  contextMenu.popup()
                              }
                          }
                      }
                  }
              }
              Item {
                  id: placeholder
                  anchors { top: toolBar.bottom; left: parent.left; right: parent.right; bottom: parent.bottom }
              }
              states: [
                  State {
                      name: "undocked"
                      PropertyChanges { target: root; height: 0 }
                      PropertyChanges { target: window; visible: true }
                      ParentChange { target: content; parent: undockedContainer }
                      //PropertyChanges { target: window; visible: true; x: 250; y: 250 }
                      //this is to make sure the width becomes zero and rest of the control takes the realstate
                      PropertyChanges {target: navigationWindow; width: 0 }
                      PropertyChanges {target: toolBar; Material.background: "#f0e68c" }
                      PropertyChanges {target: unDockMenu; enabled: false }
                      PropertyChanges {target: dockMenu; enabled: true }
                  },
                  State {
                      name: "docked"
                      PropertyChanges { target: root; height: implicitHeight }
                      PropertyChanges { target: window; visible: false }
                      ParentChange { target: content; parent: root }
                      PropertyChanges {target: unDockMenu; enabled: true }
                      PropertyChanges {target: dockMenu; enabled: false }
                  }
              ]
          }
          Window {
              id: window
              width: 250;
              height: 700;
              
              flags: Qt.FramelessWindowHint
              
              Item {
                  id: undockedContainer
                  anchors.fill: parent           
              }
              
              onClosing: {
                  content.state = "docked"
              }
          }
      }
      
      K Offline
      K Offline
      kaushikv
      wrote on last edited by
      #2

      Hi QML experts,

      Can anyone help me in resolving/fixing the issue that I am facing?

      Thanks,

      T 1 Reply Last reply
      0
      • K kaushikv

        Hi QML experts,

        Can anyone help me in resolving/fixing the issue that I am facing?

        Thanks,

        T Offline
        T Offline
        ThibaultG
        wrote on last edited by
        #3

        Hi @kaushikv,
        Anything new about this issue?
        I have the same needs and I would like to know if you succeed.

        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