How to make a resizable rectangle in QML?
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
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: