I have following challenge
I have to simulate a rotary knob. Both green cicles are fix, the yellow one should be rotated around the dark green one on mouse drag.
To keep this simple, I calculate the angle by which the outer rectangle (the light green one) must be rotated depending on the mouse position.
This almost works, but it flickers massive with every mouse movement and it looks like the yellow circle always jumps back to the starting position.
Here my code
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Rectangle {
id: encoder
color: "lightgreen";
height: 150;
width: height;
radius: (height / 2);
property real centerX : (width / 2);
property real centerY : (height / 2);
antialiasing: true;
Rectangle {
id: center
color: "darkgreen";
height: parent.height * 0.4;
width: height;
radius: (height / 2);
border.color: "black"
border.width: 0
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
MouseArea {
anchors.fill: parent
onPressed: center.border.width = 2
onReleased: center.border.width = 0
}
}
Rectangle {
id: wheel
color: "yellow";
height: parent.height * 0.2
width: height
radius: (height / 2)
anchors {
top: parent.top;
margins: 10;
horizontalCenter: parent.horizontalCenter;
}
MouseArea{
id: mouseArea
anchors.fill: parent;
onPositionChanged: {
var point = mapToItem (encoder, mouse.x, mouse.y);
var diffX = (point.x - encoder.centerX)
var diffY = -1 * (point.y - encoder.centerY)
var rad = Math.atan (diffY / diffX)
var deg = (rad * 180 / Math.PI)
if (diffX > 0 && diffY > 0) {
encoder.rotation = 90 - Math.abs (deg);
}
else if (diffX > 0 && diffY < 0) {
encoder.rotation = 90 Math.abs (deg);
}
else if (diffX < 0 && diffY > 0) {
encoder.rotation = 270 Math.abs (deg);
}
else if (diffX < 0 && diffY < 0) {
encoder.rotation = 270 - Math.abs (deg);
}
else
console.log ("nix");
}
}
}
}
Thanks and best regards
Arne
CodePudding user response:
The issue with your approach is that the encoder
item is rotating and this will be part of the mouse position mapping as well. You can see that clearly when you rotate half way and then release and grab again. Each following rotation will toggle between two completely different rotation angles hence the flickering.
I solved the issue by giving your component a base Item
which is static (not affected by rotation) and used for the mapping.
Edit: I've improved the rotation calculation by utilizing Qt.vector2d
and the steps described