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. switching from QGraphicsView to QML
Forum Updated to NodeBB v4.3 + New Features

switching from QGraphicsView to QML

Scheduled Pinned Locked Moved Solved QML and Qt Quick
11 Posts 2 Posters 4.5k Views 2 Watching
  • 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.
  • sierdzioS Offline
    sierdzioS Offline
    sierdzio
    Moderators
    wrote on last edited by
    #2

    Some basic way to achieve this:

    Item { // Assuming this is your floor item
      onXChanged: if (x < 0) x = 0
      onYChanged: if (y < 0) y = 0
    }
    

    Or if you use anchors/ layouts to position items, you kind of get this for free. Modifying position can then be achieved by specifying anchor margins.

    (Z(:^

    M 1 Reply Last reply
    0
    • sierdzioS sierdzio

      Some basic way to achieve this:

      Item { // Assuming this is your floor item
        onXChanged: if (x < 0) x = 0
        onYChanged: if (y < 0) y = 0
      }
      

      Or if you use anchors/ layouts to position items, you kind of get this for free. Modifying position can then be achieved by specifying anchor margins.

      M Offline
      M Offline
      Marek
      wrote on last edited by
      #3

      @sierdzio thanks for hint. I'm quite new to QML although I'm writing widget apps for some years.
      So now I have main.qml and SwipeView with two pages, second one is for QGraphicsView equivalent
      Is there any equivalent in QML ?

      With anchor approach it would be something like ?:

      MainItem {
          anchor.left: parent.left - (calculated size diff between MainItem width and screen width)
      |
      

      this size should be calculated whenever user stretches MainItem, right?

      1 Reply Last reply
      0
      • sierdzioS Offline
        sierdzioS Offline
        sierdzio
        Moderators
        wrote on last edited by
        #4

        There is no equivalent ot QGraphicsView in QML. They work on different principles. I strongly recommend doing some simple apps first, just to get the hang of it. QML is easy to learn, but you will need some time to get adjusted to different way of thinking than in imperative code.

        Regarding anchors. You can't add or substract anything from an anchor. You can modify the margin, however.

        MainItem {
            anchors.left: parent.left
            anchors.leftMargin: 20
        }
        

        Another possibility: consider using Flickable element. I think it might work out very well in your use case. It already supports zooming and flicking, just like you need. And you can get the exact behaviour you need using boundsBehaviour property. Exact position of content item (your floor) can be accessed with contentY and contentX properties, etc.

        (Z(:^

        M 1 Reply Last reply
        1
        • sierdzioS sierdzio

          There is no equivalent ot QGraphicsView in QML. They work on different principles. I strongly recommend doing some simple apps first, just to get the hang of it. QML is easy to learn, but you will need some time to get adjusted to different way of thinking than in imperative code.

          Regarding anchors. You can't add or substract anything from an anchor. You can modify the margin, however.

          MainItem {
              anchors.left: parent.left
              anchors.leftMargin: 20
          }
          

          Another possibility: consider using Flickable element. I think it might work out very well in your use case. It already supports zooming and flicking, just like you need. And you can get the exact behaviour you need using boundsBehaviour property. Exact position of content item (your floor) can be accessed with contentY and contentX properties, etc.

          M Offline
          M Offline
          Marek
          wrote on last edited by
          #5

          @sierdzio Thanks for flickable example, there is also one in QtCreator which I will try to implement.
          I have an impression that I have seen somewhere in examples that right part of the binding was an expression calculated from some function in javascript or from C++ bindings.

          Best Regards
          Marek

          1 Reply Last reply
          0
          • sierdzioS Offline
            sierdzioS Offline
            sierdzio
            Moderators
            wrote on last edited by
            #6

            @Marek said in switching from QGraphicsView to QML:

            I have an impression that I have seen somewhere in examples that right part of the binding was an expression calculated from some function in javascript or from C++ bindings.

            Yes, that is correct. You can easily write stuff like:

            x: 15 * someProperty
            y: 80 + SomeQObject.someFunction()
            

            etc. However, in case of anchors property, it expects not a numerical value, but an actual anchor from another object. Hence in that case, margins are needed.

            (Z(:^

            M 1 Reply Last reply
            0
            • sierdzioS sierdzio

              @Marek said in switching from QGraphicsView to QML:

              I have an impression that I have seen somewhere in examples that right part of the binding was an expression calculated from some function in javascript or from C++ bindings.

              Yes, that is correct. You can easily write stuff like:

              x: 15 * someProperty
              y: 80 + SomeQObject.someFunction()
              

              etc. However, in case of anchors property, it expects not a numerical value, but an actual anchor from another object. Hence in that case, margins are needed.

              M Offline
              M Offline
              Marek
              wrote on last edited by
              #7

              @sierdzio I have copied flick-resize into my app and played for a while, seems to be what I need.
              Howver, I cant work out how to have two images parent and a children, where children is also affected by pinch gesture
              For instance, child image is positioned in (100,100)px of the main mapImage, then pinch gesture resizes the mapImage but child image remains in the same scale and in fixed position over the scaled image.

              Flickable {
                      id: flick
                      anchors.fill: parent
                      contentWidth: 4109
                      contentHeight: 824
              
                      PinchArea {
                          id:pinch
                          width: Math.max(flick.contentWidth, flick.width)
                          height: Math.max(flick.contentHeight, flick.height)
              
                          property real initialWidth
                          property real initialHeight
                          //![0]
                          onPinchStarted: {
                              initialWidth = flick.contentWidth
                              initialHeight = flick.contentHeight
                          }
              
                          onPinchUpdated: {
                              // adjust content pos due to drag
                              flick.contentX += pinch.previousCenter.x - pinch.center.x
                              flick.contentY += pinch.previousCenter.y - pinch.center.y
              
                              // resize content
                              if(initialWidth * pinch.scale>500 && initialHeight * pinch.scale>200)
                                  flick.resizeContent(initialWidth * pinch.scale, initialHeight * pinch.scale, pinch.center)
                          }
              
                          onPinchFinished: {
                              // Move its content within bounds.
                              flick.returnToBounds()
                              console.log("pinch updated width:"+flick.contentWidth+" height:"+flick.contentHeight+" scale:"+pinch.scale)
                          }
                          //![0]
              
                          Rectangle {
                              width: flick.contentWidth
                              height: flick.contentHeight
                              color: "white"
                              Image {
                                  id: mapImage
                                  anchors.fill: parent
                                  source: "images/mapa.jpg"
                                  MouseArea {
                                      anchors.fill: parent
                                      onDoubleClicked: {
                                          flick.contentWidth = 4109
                                          flick.contentHeight = 824
                                      }
                                  }
                                  onScaleChanged: {
                                      console.log("scale changed:"+scale)
                                  }
                                  Image {
                                      id: childImage
                                      x: 100
                                      y: 100
                                      source: "images/seat_icon.jpg"
                                  }
                              }
                          }
                      }
                  }
              

              Is this a parent-child relation problem ? Scale of the mapImage does not change.
              I'm looking for a similar behavior as with QGraphicsPixmapItem. When I have parent and child and I apply setScale to parent child is also scaled and his position is in parent coordinates so it seems it moves with parent image when it is resized.

              Best Regards
              Marek

              M 1 Reply Last reply
              0
              • M Marek

                @sierdzio I have copied flick-resize into my app and played for a while, seems to be what I need.
                Howver, I cant work out how to have two images parent and a children, where children is also affected by pinch gesture
                For instance, child image is positioned in (100,100)px of the main mapImage, then pinch gesture resizes the mapImage but child image remains in the same scale and in fixed position over the scaled image.

                Flickable {
                        id: flick
                        anchors.fill: parent
                        contentWidth: 4109
                        contentHeight: 824
                
                        PinchArea {
                            id:pinch
                            width: Math.max(flick.contentWidth, flick.width)
                            height: Math.max(flick.contentHeight, flick.height)
                
                            property real initialWidth
                            property real initialHeight
                            //![0]
                            onPinchStarted: {
                                initialWidth = flick.contentWidth
                                initialHeight = flick.contentHeight
                            }
                
                            onPinchUpdated: {
                                // adjust content pos due to drag
                                flick.contentX += pinch.previousCenter.x - pinch.center.x
                                flick.contentY += pinch.previousCenter.y - pinch.center.y
                
                                // resize content
                                if(initialWidth * pinch.scale>500 && initialHeight * pinch.scale>200)
                                    flick.resizeContent(initialWidth * pinch.scale, initialHeight * pinch.scale, pinch.center)
                            }
                
                            onPinchFinished: {
                                // Move its content within bounds.
                                flick.returnToBounds()
                                console.log("pinch updated width:"+flick.contentWidth+" height:"+flick.contentHeight+" scale:"+pinch.scale)
                            }
                            //![0]
                
                            Rectangle {
                                width: flick.contentWidth
                                height: flick.contentHeight
                                color: "white"
                                Image {
                                    id: mapImage
                                    anchors.fill: parent
                                    source: "images/mapa.jpg"
                                    MouseArea {
                                        anchors.fill: parent
                                        onDoubleClicked: {
                                            flick.contentWidth = 4109
                                            flick.contentHeight = 824
                                        }
                                    }
                                    onScaleChanged: {
                                        console.log("scale changed:"+scale)
                                    }
                                    Image {
                                        id: childImage
                                        x: 100
                                        y: 100
                                        source: "images/seat_icon.jpg"
                                    }
                                }
                            }
                        }
                    }
                

                Is this a parent-child relation problem ? Scale of the mapImage does not change.
                I'm looking for a similar behavior as with QGraphicsPixmapItem. When I have parent and child and I apply setScale to parent child is also scaled and his position is in parent coordinates so it seems it moves with parent image when it is resized.

                Best Regards
                Marek

                M Offline
                M Offline
                Marek
                wrote on last edited by
                #8

                I have modified example to work with onWheel signal, easier to work with on desktop.
                Child image item is repositioned, but there is slight error with position, due to setting "scale" for child item.
                Child Image moves towards bottom right corner when I scale down main image.
                Can someone advice me on how to keep this child image in fixed position when flickable element is resized ?

                Flickable {
                        id: flick
                        anchors.fill: parent
                        contentWidth: 4109
                        contentHeight: 824
                
                        Image {
                            id: mapImage
                            anchors.fill: parent
                            source: "images/mapa.jpg"
                            property real itemScale: 1
                            MouseArea {
                                anchors.fill: parent
                
                                onWheel: {
                                    if(wheel.angleDelta.y>0)
                                        parent.itemScale+=0.1
                                    else
                                        parent.itemScale+=-0.1 
                                     flick.resizeContent(mapImage.sourceSize.width*parent.itemScale,mapImage.sourceSize.height*parent.itemScale,Qt.point(mouseX,mouseY))
                
                                    flick.returnToBounds()
                                }
                            }
                            Image {
                                id: childImage
                                x: 100*parent.itemScale
                                y: 100*parent.itemScale
                                scale: parent.itemScale
                                source: "images/seat_icon.jpg"
                
                            }
                        }
                    }
                

                Best Regards
                Marek

                1 Reply Last reply
                0
                • sierdzioS Offline
                  sierdzioS Offline
                  sierdzio
                  Moderators
                  wrote on last edited by sierdzio
                  #9

                  @Marek said in switching from QGraphicsView to QML:

                  anchors.fill: parent

                  I suspect that might be the issue: you are trying to anchor to an object that is designed for scrolling (that is: it is designed to handle components larger than itself).

                  So, my recommendations:

                  • remove anchors from mapImage
                  • give mapImage a fixed size
                  • when zooming/ pinching, modify scale of mapImage

                  Feel free to take a look at/clone/reuse my code from CCF it's old, very old code, but it used to work and scale contents of a Flickable correctly.

                  (Z(:^

                  M 1 Reply Last reply
                  1
                  • sierdzioS sierdzio

                    @Marek said in switching from QGraphicsView to QML:

                    anchors.fill: parent

                    I suspect that might be the issue: you are trying to anchor to an object that is designed for scrolling (that is: it is designed to handle components larger than itself).

                    So, my recommendations:

                    • remove anchors from mapImage
                    • give mapImage a fixed size
                    • when zooming/ pinching, modify scale of mapImage

                    Feel free to take a look at/clone/reuse my code from CCF it's old, very old code, but it used to work and scale contents of a Flickable correctly.

                    M Offline
                    M Offline
                    Marek
                    wrote on last edited by
                    #10

                    @sierdzio Thanks for hint and for Your help, I will look into your code.
                    I have just returned from the gym and during workout I have figured out the problem ;) Probably more oxygen for the brain.
                    Instead of child Image which need to be scaled (and then the problem appears) I have Rectangle which is scaled, and inside rectangle there is an image. Works very well.

                    Rectangle {
                        width:sourceImageWidth*parent.itemScale
                        height:sourceImageHeight*parent.itemScale
                        x: 100*parent.itemScale
                        y: 100*parent.itemScale
                        Image {
                            id: childImage
                            anchors.fill: parent
                            source: "images/seat_icon.jpg"
                    
                        }
                    }
                    

                    Just need to check whether this will work well with 100 child Images on top the mapImage.
                    So partly solved ;) Now I need to load them dynamically so next questions will follow ;)

                    Best Regards
                    Marek

                    1 Reply Last reply
                    1
                    • sierdzioS Offline
                      sierdzioS Offline
                      sierdzio
                      Moderators
                      wrote on last edited by
                      #11

                      OK, good news. Happy coding :-)

                      (Z(:^

                      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