Home > database >  QT QML rectangle flickers when rotated by mouse
QT QML rectangle flickers when rotated by mouse

Time:01-11

I have following challenge

enter image description here

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 enter image description here

  • Related