A bug of Item position in Qt Quick2
-
I think this is a bug.
When the rotation is 0, everything is ok, we can set new width or height normally.
When the rotation is not 0, if I set the new width or height, I find that the item will move to other place while the x and y property stay the same.
You can use the following code to test
@import QtQuick 2.0Rectangle {
id: root
width: 800
height: 800
color: "yellow"
Rectangle {
id: tester
rotation: 40
width: 50
height: 50
x:200
y:200
color: "black"
NumberAnimation on width {
loops: Animation.Infinite
from: 50
to: 300
duration: 1000
}
onWidthChanged: {
var pos = mapToItem(tester.parent,0, 0)
console.log("this is the position of the topleft corner of item tester:"+pos.x)
console.log("this is the x pos of item tester:"+tester.x)
}
}
}
@In my app, I want to add a controller to let user resize the item in the view(similar to what Qt Designer does), I want the Item to stay at the same position (whether the topleft corner keeps still or the center point keeps still is ok) when the rotation is not zero, but I don't know how to do that.
Hope someone can help me, thank you.
-
If you think it's a bug, then please report it in jira.
The guide for how to report bug:
http://qt-project.org/wiki/ReportingBugsInQt -
I don't think it is a bug, it is just the way rotation has been implemented. Maybe you will get better results if instead of directly using the rotation property you use a Rotation element:
@Rectangle {
id: tester
//rotation: 40
transform: Rotation {
angle: 40
}@That should work as expected.
-
You need to set the transformOrigin. See
http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick2-item.html#transformOrigin-prop
-
The explanation for this "bug" is quite logical - the rotation property always rotates around the center, and with the rotation angle being restrained to a fixed value resizing an element moves its origin, since the size itself is not relative to the center but to the top left.
-
Thank you , this really helps.
But I have one more question, what do x and y stand for, at first I thought it stands for the position of the topleft corner, but obviously it is not. I tried to search the documents but can't get the result.
[quote author="utcenter" date="1363773915"]The explanation for this "bug" is quite logical - the rotation property always rotates around the center, and with the rotation angle being restrained to a fixed value resizing an element moves its origin, since the size itself is not relative to the center but to the top left.[/quote]
-
Perhaps I didn't worded that explanation quite as accurately as I wanted. But like most people here, I am not a native English speaker.
x and y is indeed the top left corner - you could easily verify that by putting a 10 by 10 rectangle at position 10 10. That is where the mismatch comes from - rotation uses the center and position and size use the top left.
Adding a Rotation element as in my first post solves that by creating an additional origin of rotation so the position of the Rectangle is undisturbed.
-
Thank you for your patience. I am not a native English speaker either : )
I want to rotate the item around the center point, so I write the code below, but still get the same problem.
@import QtQuick 2.0
Rectangle {
id: root
width: 800
height: 800
color: "yellow"
Rectangle {
id: tester
transform: Rotation{
id: rotationItem
angle: 40
origin.x: tester.width/2
origin.y: tester.height/2
// NumberAnimation on angle {
// loops: Animation.Infinite
// from: 0
// to: 360
// duration: 1000
// }
}width: 50 height: 50 x:200 y:200 color: "black" NumberAnimation on width { loops: Animation.Infinite from: 50 to: 300 duration: 1000 } onWidthChanged: { var pos = mapToItem(tester.parent,0, 0) console.log("this is the position of the topleft corner of item tester:"+pos.x) console.log("this is the x pos of item tester:"+tester.x) } }
}
@I think I could modify x and y value when width changes so I can make the item not move, but I don't know how to modify the x and y value(this is not the right way to achieve the effect, but I can't find out another way)
Maybe you have noticed that I have added two "console.log" function, I don't know why mapToItem(tester.parent,0, 0).x does not equal to tester.x
[quote author="utcenter" date="1363776949"]Perhaps I didn't worded that explanation quite as accurately as I wanted. But like most people here, I am not a native English speaker.
x and y is indeed the top left corner - you could easily verify that by putting a 10 by 10 rectangle at position 10 10. That is where the mismatch comes from - rotation uses the center and position and size use the top left.
Adding a Rotation element as in my first post solves that by creating an additional origin of rotation so the position of the Rectangle is undisturbed.[/quote]
-
I think I have known how to do it. The key point is just to keep one transformOrigin - the TopLeft one, then I can adjust x and y to make the black rect can both rotate around its center and adjust the width and height.
Thank you.
[quote author="utcenter" date="1363780500"]What is it that you want to achieve exactly?
Have the black rectangle rotate around its center while its width changes proportional to both sides plus the ability to move the item?
Or something else?[/quote]
-
Just use a placeholder to center your rotating item into. Here is an example - the rotating item will move with the mouse cursor as it rotates around its center and changes width:
@Rectangle {
id: root
width: 800
height: 800
color: "yellow"MouseArea { id: cursorLocation hoverEnabled: true anchors.fill: parent } Item { // placeholder width: 50 height: 50 x: cursorLocation.mouseX - width/2 y: cursorLocation.mouseY - height/2 Rectangle { id: tester anchors.centerIn: parent width: 50 height: 50 color: "black" NumberAnimation on rotation { loops: Animation.Infinite from: 0 to: 360 duration: 1000 } NumberAnimation on width { loops: Animation.Infinite from: 50 to: 300 duration: 1000 } } }
}@