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. [SOLVED]QML mouse selection rectangle

[SOLVED]QML mouse selection rectangle

Scheduled Pinned Locked Moved QML and Qt Quick
canvasselectionmouseflickable
6 Posts 3 Posters 7.3k 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.
  • M Offline
    M Offline
    mcallegari79
    wrote on last edited by p3c0
    #1

    Hi everyone,
    just throwing this topic here in search of ideas if anyone has already stumbled on this matter.
    I need to implement a mouse selection area in QML.
    Something like this:
    http://www.codeproject.com/KB/WPF/SimpleDragSelection/SimpleDragSelection1.png

    I am inside a Flickable element containing a Canvas.
    My idea is to do it with some drag&drop properties, showing and resizing a semi-transparent Rectangle as long as the mouse button is pressed.

    Is there any efficient way you can think of ?
    Any help is greatly appreciated.
    If I come up with a working solution soon, I will post it here.

    Thanks !

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mcallegari79
      wrote on last edited by
      #2

      Adding one bit.

      The Flickable item steals every mouse click.
      I want the selection rectangle to be activated with the SHIFT key modifier only.
      Is there a way to tell Flickable to ignore the mouse events if the SHIFT key is pressed ?

      1 Reply Last reply
      0
      • M Offline
        M Offline
        mcallegari79
        wrote on last edited by mcallegari79
        #3

        OK, took me a couple of hours to implement it.
        Here's the code. Might not be 100% perfect but it gives the idea:

        Rectangle {
                id: selectionRect
                visible: false
                x: 0
                y: 0
                z: 99
                width: 0
                height: 0
                rotation: 0
                color: "#5F227CEB"
                border.width: 1
                border.color: "#103A6E"
                transformOrigin: Item.TopLeft
            }
        
            MouseArea {
                id: selectionMouseArea
                property int initialXPos
                property int initialYPos
                property bool justStarted
        
                anchors.fill: parent
                z: 2 // make sure we're above other elements
                onPressed: {
                    if (mouse.button == Qt.LeftButton && mouse.modifiers & Qt.ShiftModifier)
                    {
                        console.log("Mouse area shift-clicked !")
                        // initialize local variables to determine the selection orientation
                        initialXPos = mouse.x
                        initialYPos = mouse.y
                        justStarted = true
        
                        flickableView.interactive = false // in case the event started over a Flickable element
                        selectionRect.x = mouse.x
                        selectionRect.y = mouse.y
                        selectionRect.width = 0
                        selectionRect.height = 0
                        selectionRect.visible = true
                    }
                }
                onPositionChanged: {
                    if (selectionRect.visible == true)
                    {
                        if (justStarted == true && (mouse.x != initialXPos || mouse.y != initialYPos))
                        {
                            if (mouse.x >= initialXPos)
                            {
                                if (mouse.y >= initialYPos)
                                   selectionRect.rotation = 0
                                else
                                   selectionRect.rotation = -90
                            }
                            else
                            {
                                if (mouse.y >= initialYPos)
                                    selectionRect.rotation = 90
                                else
                                    selectionRect.rotation = -180
                            }
        
                            justStarted = false
                            //console.log("Selection rotation: " + selectionRect.rotation)
                        }
        
                        if (selectionRect.rotation == 0 || selectionRect.rotation == -180)
                        {
                            selectionRect.width = Math.abs(mouse.x - selectionRect.x)
                            selectionRect.height = Math.abs(mouse.y - selectionRect.y)
                        }
                        else
                        {
                            selectionRect.width = Math.abs(mouse.y - selectionRect.y)
                            selectionRect.height = Math.abs(mouse.x - selectionRect.x)
                        }
                    }
                }
        
                onReleased: {
                    selectionRect.visible = false
                    // restore the Flickable duties
                    flickableView.interactive = true
                }
            }
        
        1 Reply Last reply
        0
        • M Offline
          M Offline
          mcallegari79
          wrote on last edited by
          #4

          Now how the heck do I mark this thread as "solved" ?
          Quoting:

          The ‘thread tools’ at the bottom of a thread let the poster or moderators ‘mark a thread as solved’. This will add a ‘Solved’ tag to the post in the category view to help people find solved posts easily.

          The only option I have is "Delete topic"...nice...

          1 Reply Last reply
          0
          • X Offline
            X Offline
            xargs1
            wrote on last edited by
            #5

            Add [SOLVED] to the beginning of the subject line.

            1 Reply Last reply
            0
            • D Offline
              D Offline
              damianatorrpm
              wrote on last edited by
              #6

              In case you come across this a bit more complete example, including handling of contentY changing because of scroll...:

              MouseArea
              {id: selectionMouseArea
              property alias selectionRect : selectionRect
              property int initialXPos
              property int initialYPos
              property int mouseX
              property int mouseY
              anchors.fill: grid
              acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton

              Rectangle
              {id: selectionRect
                  visible: false
                  x: 0
                  y: 0
                  z: 99
                  width: 0
                  height: 0
                  rotation: 0
                  radius: 5
                  color: "#5F227CEB"
                  border.width: 1
                  border.color: "#103A6E"
                  transformOrigin: Item.TopLeft
              } //selectionRect
              
               //moving close to top or bot end scrolls view depending on speed
              Timer {repeat: true;running: ( parent.mouseY < 0 && grid.contentY>0 ) && parent.pressed && !grid.atYBeginning;
                  interval: 10; onTriggered: grid.contentY -= (-1 * parent.mouseY), returnToBounds()
              }
              Timer {repeat: true;running: ( parent.mouseY > grid.height) && parent.pressed  && !grid.atYEnd
                  interval: 10; onTriggered: grid.contentY += 1 * ( parent.mouseY -grid.height ), returnToBounds()
              }
              
              //makes the rectangle smooth
              Connections
              {
                  target: grid
                  onContentYChanged: //selectionRect needs to be depending onConentY as its size and position depends on that
                  {
                      if (selectionRect.rotation == 0 || selectionRect.rotation == -180)
                      {
                          selectionRect.y = selectionMouseArea.initialYPos - grid.contentY
                          selectionRect.height = Math.abs(selectionMouseArea.mouseY - selectionMouseArea.initialYPos + grid.contentY)
                          selectionRect.width = Math.abs(selectionMouseArea.mouseX - selectionRect.x)
                      }
                      else
                      {
                          selectionRect.y =  selectionMouseArea.initialYPos - grid.contentY
                          selectionRect.height = Math.abs(selectionMouseArea.mouseX - selectionRect.x)
                          selectionRect.width = Math.abs(selectionMouseArea.mouseY - selectionRect.y)
                      }
                  }
              }
              
              onClicked:
              {
                  if(mouse.button == Qt.RightButton)
                  {
                      mouse.accepted=false
                      return;
                  }
                  if ( wasHeld || mouse.modifiers & Qt.ControlModifier )
                      return;
                  initialXPos=mouse.x; initialYPos=mouse.y;mouseX=mouse.x;mouseY=mouse.y
                  
              }
              onPressed:
              {
                  if(mouse.button == Qt.RightButton)
                  {
                      mouse.accepted=false
                      return;
                  }
                  if (mouse.modifiers & Qt.ControlModifier)
                      {
                      console.log("ControlModifier");
                      mouse.accepted=false
                      return;
                  }
                  if (mouse.button == Qt.LeftButton)
                  {
              
              
                      initialXPos = mouse.x
                      initialYPos = mouse.y+grid.contentY
                      
                      grid.interactive = false
                      selectionRect.x = mouse.x
                      selectionRect.y = mouse.y
                      selectionRect.width = 0
                      selectionRect.height = 0
                  }
                  if(itemAt(mouse.x,mouse.y+grid.contentY).hovered)
                      mouse.accepted=false
                  if(itemAt(mouse.x,mouse.y+grid.contentY).hovered===false)
                  {
                      ufm().resetSelection()
                  grid.currentIndex=-1
              }
              }
              onPositionChanged:
              {
                //  console.log(selectionRect.height);
                 // console.log(selectionRect.width);
              
                  if(mouse.button == Qt.RightButton)
                  {
                      mouse.accepted=false
                      return;
                  }
                  if (mouse.modifiers & Qt.ControlModifier)
                      {
                      return;
                  }
                  selectionRect.visible = true
              
                  if (selectionRect.visible === false)
                  {
                      selectionRect.x = 0
                      selectionRect.y = 0
                      selectionRect.width = 0
                      selectionRect.height = 0
              
                      initialXPos = 0
                      initialYPos = 0
                  }
              
                  if (selectionRect.visible === true)
                  {
                      mouseX = mouse.x
                      mouseY = mouse.y
                      if (Math.abs(mouseX, initialXPos)>30) wasHeld = true
                      if (Math.abs(mouseY, initialYPos)>30) wasHeld = true
              
                      if (mouse.x >= initialXPos)
                      {
                          if (mouse.y+grid.contentY >= initialYPos)
                              selectionRect.rotation = 0
                          else
                              selectionRect.rotation = -90
                      }
                      else if (mouse.x <= initialXPos)
                      {
                          if (mouse.y+grid.contentY >= initialYPos)
                              selectionRect.rotation = 90
                          else
                              selectionRect.rotation = -180
                      }
                      if (selectionRect.rotation == 0 || selectionRect.rotation == -180)
                      {               
                          selectionRect.y = initialYPos - grid.contentY
                          selectionRect.height = Math.abs(mouse.y - initialYPos + grid.contentY)
                          selectionRect.width = Math.abs(mouse.x - selectionRect.x)
                      }
                      else
                      {
                          selectionRect.y = initialYPos - grid.contentY
                          selectionRect.height = Math.abs(mouse.x - selectionRect.x)
                          selectionRect.width = Math.abs(mouse.y - selectionRect.y)
                      }
                  }
              }
              
              onReleased:
              {
                  selectionRect.visible = false
              
                  // restore the Flickable duties
                  grid.interactive = true
              }
              onWheel:
              {
                  if (wheel.angleDelta.y > 0 && !grid.atYBeginning) grid.contentY -= 50
                  else if (wheel.angleDelta.y < 0 && !grid.atYEnd) grid.contentY += 50
              }
              

              }

              1 Reply Last reply
              1

              • Login

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