QML PhotoShop like Transform Control



  • !https://lh3.googleusercontent.com/-2gr-oT-7swQ/Tnqtv-06zpI/AAAAAAAAAGM/OjSExWkKFgs/s360/TransformControlEx.gif(TransfromControlEx)!

    I am trying to create a PhotoShop like transform control as a QML Component. I am doing this by creating a series of circles and line, and then parenting them to a draggable image. Moving the different circles around the the image scale and rotate the image just like in PS. The problem is that since the transform control is a child of the image, the circle are getting scaled also. How would I go about keep this from happening the child of a component from scaling with the parent?



  • Tranform Control
    @import QtQuick 1.0

    Rectangle {
    id: transControl
    width: parent.width
    height: parent.height
    color: "#00000000"
    anchors.fill: parent

    property int gripSize: 10
    property int gripZ: 25
    property double originalWidth: width
    
    Rectangle {
        id: border
        width: parent.width
        height: parent.height
        color: "#00000000"
        border.color: "#000000"
        z: 0
    
        ResizeGrip {
            id: topLeftGrip
            type: "topLeft"
            width: transControl.gripSize
            height: transControl.gripSize
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.horizontalCenterOffset: 0 - parent.width / 2
            anchors.verticalCenter: parent.verticalCenter
            anchors.verticalCenterOffset: 0 - parent.height / 2
            z: gripZ
        }
    
        ResizeGrip {
            id: topMiddleGrip
            type: "topMiddle"
            width: transControl.gripSize
            height: transControl.gripSize
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.verticalCenter: parent.verticalCenter
            anchors.verticalCenterOffset: 0 - parent.height / 2
            z: gripZ
        }
    
        ResizeGrip {
            id: topRightGrip
            type: "topRight"
            width: transControl.gripSize
            height: transControl.gripSize
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.horizontalCenterOffset: 0 + parent.width / 2
            anchors.verticalCenter: parent.verticalCenter
            anchors.verticalCenterOffset: 0 - parent.height / 2
            z: gripZ
        }
    
        ResizeGrip {
            id: midLeftGrip
            type: "middleLeft"
            width: transControl.gripSize
            height: transControl.gripSize
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.horizontalCenterOffset: 0 - parent.width / 2
            anchors.verticalCenter: parent.verticalCenter
            z: gripZ
        }
    
        ResizeGrip {
            id: midRightGrip
            type: "middleRight"
            width: transControl.gripSize
            height: transControl.gripSize
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.horizontalCenterOffset: 0 + parent.width / 2
            anchors.verticalCenter: parent.verticalCenter
            z: gripZ
            Scale{
                id: mrScale
                origin.x: midLeftGrip.x
                origin.y: midLeftGrip.y
                xScale: .5
            }
            MouseArea{
                id: ma
                anchors.fill: parent
                drag.axis: Drag.XAxis
                drag.target: midRightGrip
                onPressed: {
                    console.log(midRightGrip.type + " was pressed");
                    midRightGrip.anchors.horizontalCenter = undefined;
                }
                onReleased: {
                    console.log(midRightGrip.type + " was released");
                    midRightGrip.anchors.horizontalCenter = midRightGrip.parent.horizontalCenter;
                }
            }
            onXChanged: {
                var parent = transControl.parent
                if (ma.drag.active){
                    var distance = Math.abs(midRightGrip.x - midLeftGrip.x)
                    mrScale.xScale = distance
                    mrScale.xScale = distance / transControl.originalWidth
                    parent.transform = mrScale
                    console.log(transControl.originalWidth)
                    console.log("Distance is " + distance)
                    console.log("Scale is " + mrScale.xScale)
                    console.log(midRightGrip.type + " moved to " + midRightGrip.x)
                }
            }
        }
    
        ResizeGrip {
            id: rgtLeftGrip
            type: "rightLeft"
            width: transControl.gripSize
            height: transControl.gripSize
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.horizontalCenterOffset: 0 - parent.width / 2
            anchors.verticalCenter: parent.verticalCenter
            anchors.verticalCenterOffset: parent.height / 2
            z: gripZ
        }
    
        ResizeGrip {
            id: rgtMiddleGrip
            type: "rightMiddle"
            width: transControl.gripSize
            height: transControl.gripSize
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.verticalCenter: parent.verticalCenter
            anchors.verticalCenterOffset: parent.height / 2
            z: gripZ
        }
    
        ResizeGrip {
            id: rgtRightGrip
            type: "rightRight"
            width: transControl.gripSize
            height: transControl.gripSize
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.horizontalCenterOffset: 0 + parent.width / 2
            anchors.verticalCenter: parent.verticalCenter
            anchors.verticalCenterOffset: parent.height / 2
            z: gripZ
        }
    }
    

    }
    @



  • Code that instantiates it onto the draggable image
    @ var component = Qt.createComponent("Transform.qml");
    console.log("creating transform control");
    if (component.status == Component.Ready){
    var transform = component.createObject(di);
    transform.x = di.x - transform.width / 2
    transform.y = di.y - transform.height / 2
    }@



  • Hi,

    Rather than making your control a child of the Image you want to manipulate, can you make it a sibling? You could e.g. add a target property to transControl:

    @property Item target@

    which would be used internally where transControl.parent is currently used. Externally, you would then assign the target wherever the control is used:

    @Rectangle {
    Image { id: myImage }
    TransformControl { target: myImage }
    }@

    Regards,
    Michael



  • I have updated the transControl as you have said with
    @property Item target@

    Then, on the javascript side when I create the control with
    @var component = Qt.createComponent("Transform.qml");
    component.target = target;@

    I get this error:
    Error: Cannot assign to non-existent property "target"

    Do you know what I am doing wrong?



  • Hi,

    The target property is defined for the instances of the component, rather than the component itself, so it needs to be set on the objects returned from createObject:

    @var obj = component.createObject(parent)
    obj.target = targetItem
    @

    If you are using QtQuick 1.1 you can also do something like the following (which is faster and should potentially generate fewer warnings):

    @var obj = component.createObject(parent, { target: targetItem })

    Regards,
    Michael


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.