Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a resizable rectangle in QML?

I'm looking for a simple way to create a rectangle in a QQuickItem. I want to resize, and drag the borders of this rectangle like this (found at resizable QRubberBand)

enter image description here

Has someone an idea?

like image 973
501 - not implemented Avatar asked Mar 16 '15 21:03

501 - not implemented


People also ask

What is rectangle in QML?

Rectangle items are used to fill areas with solid color or gradients, and/or to provide a rectangular border.

What is implicit width in QML?

implicitWidth : realDefines the natural width or height of the Item if no width or height is specified. The default implicit size for most items is 0x0, however some items have an inherent implicit size which cannot be overridden, for example, Image and Text .


2 Answers

There are probably several ways to achieve the desired result. Since I've considered the implementation of a similar Component for a cropping tool software of mine, I'm going to share a toy example which uses part of that code.

Differently from the rubber band in the example, my Rectangle is resizable only on a single axis at a time. I'm confident that you can build on that and customise the code to meet your needs.

The basic idea of the code is to exploit the drag property of MouseArea. It can be used to move around the Rectangle and, combined with MouseX and MouseY properties, resize it.

Dragging is active inside the Rectangle whereas resizing is active on the knobs set on the sides of the Rectangle (no mouse cursor change is set for the sake of brevity).

import QtQuick 2.4
import QtQuick.Controls 1.3

ApplicationWindow {
    title: qsTr("Test Crop")
    width: 640
    height: 480
    visible: true
    property var selection: undefined

    Image {
        id: image1
        anchors.fill: parent
        source: "http://cdn.cutestpaw.com/wp-content/uploads/2013/01/l-Kitty-attack.jpg"

        MouseArea {
            anchors.fill: parent
            onClicked: {
                if(!selection)
                    selection = selectionComponent.createObject(parent, {"x": parent.width / 4, "y": parent.height / 4, "width": parent.width / 2, "height": parent.width / 2})
            }
        }
    }

    Component {
        id: selectionComponent

        Rectangle {
            id: selComp
            border {
                width: 2
                color: "steelblue"
            }
            color: "#354682B4"

            property int rulersSize: 18

            MouseArea {     // drag mouse area
                anchors.fill: parent
                drag{
                    target: parent
                    minimumX: 0
                    minimumY: 0
                    maximumX: parent.parent.width - parent.width
                    maximumY: parent.parent.height - parent.height
                    smoothed: true
                }

                onDoubleClicked: {
                    parent.destroy()        // destroy component
                }
            }

            Rectangle {
                width: rulersSize
                height: rulersSize
                radius: rulersSize
                color: "steelblue"
                anchors.horizontalCenter: parent.left
                anchors.verticalCenter: parent.verticalCenter

                MouseArea {
                    anchors.fill: parent
                    drag{ target: parent; axis: Drag.XAxis }
                    onMouseXChanged: {
                        if(drag.active){
                            selComp.width = selComp.width - mouseX
                            selComp.x = selComp.x + mouseX
                            if(selComp.width < 30)
                                selComp.width = 30
                        }
                    }
                }
            }

            Rectangle {
                width: rulersSize
                height: rulersSize
                radius: rulersSize
                color: "steelblue"
                anchors.horizontalCenter: parent.right
                anchors.verticalCenter: parent.verticalCenter

                MouseArea {
                    anchors.fill: parent
                    drag{ target: parent; axis: Drag.XAxis }
                    onMouseXChanged: {
                        if(drag.active){
                            selComp.width = selComp.width + mouseX
                            if(selComp.width < 50)
                                selComp.width = 50
                        }
                    }
                }
            }

            Rectangle {
                width: rulersSize
                height: rulersSize
                radius: rulersSize
                x: parent.x / 2
                y: 0
                color: "steelblue"
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.verticalCenter: parent.top

                MouseArea {
                    anchors.fill: parent
                    drag{ target: parent; axis: Drag.YAxis }
                    onMouseYChanged: {
                        if(drag.active){
                            selComp.height = selComp.height - mouseY
                            selComp.y = selComp.y + mouseY
                            if(selComp.height < 50)
                                selComp.height = 50
                        }
                    }
                }
            }


            Rectangle {
                width: rulersSize
                height: rulersSize
                radius: rulersSize
                x: parent.x / 2
                y: parent.y
                color: "steelblue"
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.verticalCenter: parent.bottom

                MouseArea {
                    anchors.fill: parent
                    drag{ target: parent; axis: Drag.YAxis }
                    onMouseYChanged: {
                        if(drag.active){
                            selComp.height = selComp.height + mouseY
                            if(selComp.height < 50)
                                selComp.height = 50
                        }
                    }
                }
            }
        }
    }
}

A screenshot of the example: enter image description here

like image 134
BaCaRoZzo Avatar answered Oct 11 '22 12:10

BaCaRoZzo


MouseArea {
            id:roiRectArea
            anchors.fill: parent

            onPressed: {
                pressX = mouse.x
                pressY = mouse.y
            }

            onReleased: {
                releaseX = mouse.x
                releaseY = mouse.y
                rectWidth = releaseX
                widthRect = releaseX - pressX
                rectHeight = releaseY
                heightRect = releaseY - pressY
            }

            onPositionChanged: {
                releaseX = mouse.x
                releaseY = mouse.y
                widthRect = releaseX - pressX
                heightRect = releaseY - pressY
            }

            Rectangle {
                id:rectRoi
                antialiasing: true
                opacity: 0.4
                x: pressX
                y: pressY
                width: widthRect
                height: heightRect
                border {
                    width: 2
                    color: "blue"
                }
                color: "#00F0F8FF"

                MouseArea {
                    anchors.fill: parent
                    drag{
                        target: rectRoi
                        minimumX: 0
                        minimumY: 0
                        maximumX: parent.parent.width - parent.width
                        maximumY: parent.parent.height - parent.height
                        smoothed: true
                    }
                    onDoubleClicked: {
                        parent.destroy()
                    }
                }

                Rectangle {
                    width: rulersSize
                    height: rulersSize
                    color: "white"
                    anchors.horizontalCenter: parent.left
                    anchors.verticalCenter: parent.top
                    id: selComp
                    MouseArea {
                        anchors.fill: parent
                        drag{ target: parent; axis: Drag.XAxis }
                        onMouseXChanged: {
                            if(drag.active){
                                var newWidth = rectRoi.width - mouseX
                                if (newWidth < 30)
                                    return
                                rectRoi.width = newWidth
                                rectRoi.x = rectRoi.x + mouseX
                            }
                        }
                        drag{ target: parent; axis: Drag.YAxis }
                        onMouseYChanged: {
                            if(drag.active){
                                var newHeight = rectRoi.height - mouseY;

                                if (newHeight < 30)
                                    return
                                rectRoi.height = newHeight
                                rectRoi.y = rectRoi.y + mouseY
                            }
                        }
                    }
                }

                Rectangle {
                    width: rulersSize
                    height: rulersSize
                    color: "red"
                    anchors.horizontalCenter: parent.left
                    anchors.verticalCenter: parent.bottom

                    MouseArea {
                        anchors.fill: parent
                        drag{ target: parent; axis: Drag.XAxis; }
                        onMouseXChanged: {
                            if(drag.active) {
                                var newWidth = rectRoi.width - mouseX
                                if (newWidth < 30)
                                    return
                                rectRoi.width = newWidth
                                rectRoi.x = rectRoi.x + mouseX
                            }
                        }
                        drag{ target: parent; axis: Drag.YAxis }
                        onMouseYChanged: {
                            if(drag.active){

                                var newHeight = rectRoi.height + mouseY;

                                if (newHeight < 30)
                                    return
                                rectRoi.height = newHeight
                            }
                        }
                    }
                }

                Rectangle {
                    width: rulersSize
                    height: rulersSize
                    color: "orange"
                    anchors.horizontalCenter: parent.right
                    anchors.verticalCenter: parent.bottom
                    MouseArea {
                        anchors.fill: parent
                        drag{ target: parent; axis: Drag.XAxis }
                        onMouseXChanged: {
                            if(drag.active){

                                var newWidth = rectRoi.width + mouseX
                                if (newWidth < 30)
                                    return
                                rectRoi.width = newWidth
                            }
                        }
                        drag{ target: parent; axis: Drag.YAxis }
                        onMouseYChanged: {
                            if(drag.active){

                                var newHeight = rectRoi.height + mouseY;

                                if (newHeight < 30)
                                    return
                                rectRoi.height = newHeight
                            }
                        }
                    }
                }

                Rectangle {
                    width: rulersSize
                    height: rulersSize
                    color: "green"
                    anchors.horizontalCenter: parent.right
                    anchors.verticalCenter: parent.top
                    MouseArea {
                        anchors.fill: parent
                        drag{ target: parent; axis: Drag.XAxis; }
                        onMouseXChanged: {
                            if(drag.active){

                                var newWidth = repeater.itemAt(index).width + mouseX
                                if (newWidth < 30)
                                    return
                                repeater.itemAt(index).width = newWidth
                            }
                        }
                        drag{ target: parent; axis: Drag.YAxis }
                        onMouseYChanged: {
                            if(drag.active) {
                                var newHeight = repeater.itemAt(index).height - mouseY;
                                if (newHeight < 30)
                                    return
                                repeater.itemAt(index).height = newHeight
                                repeater.itemAt(index).y = repeater.itemAt(index).y + mouseY
                            }
                        }
                    }
                }
            }
        }

Hope it will help someone

like image 36
ellenkis Avatar answered Oct 11 '22 11:10

ellenkis