3 votes

Qt Mouse Control of Rotaries on touch and non-touch devices (contrôle des rotations par la souris Qt sur les appareils tactiles et non tactiles)

J'ai implémenté un widget rotatif dans Qt. Lorsque l'utilisateur clique sur le bouton rotatif, le curseur de la souris est caché, et en glissant la souris vers la gauche/bas, le bouton rotatif tourne dans le sens inverse des aiguilles d'une montre, et en glissant la souris vers la droite/haut, le bouton rotatif tourne dans le sens des aiguilles d'une montre. Lorsque la souris est relâchée, le curseur reprend la position initiale du clic. Implémenté de cette manière :

void RotaryWidget::mousePressEvent(QMouseEvent *MouseEvent)
{
    mMousePos = QCursor::pos();
    mPreviousPos = MouseEvent->pos();
    setCursor(Qt::BlankCursor);
}

void RotaryWidget::mouseReleaseEvent(QMouseEvent *MouseEvent)
{
    QCursor::setPos(mMousePos);
    unsetCursor();
}

void RotaryWidget::mouseMoveEvent(QMouseEvent *MouseEvent)
{
    QPoint DeltaPos = MouseEvent->pos() - mPreviousPos;
    // Use DeltaPos to move my rotary
    mPreviousPos = MouseEvent->pos();
}

L'avantage est que lorsqu'il y a plusieurs rotatives à la suite, il est plus rapide pour l'utilisateur d'effectuer des ajustements.

Le code ci-dessus présente un problème : si le curseur atteint le bord de l'écran, la souris ne peut pas être déplacée et le bouton rotatif ne bouge donc pas. Cependant, l'utilisateur ne peut pas voir le curseur, c'est donc un problème. J'ai modifié mouseMoveEvent pour le réparer :

void RotaryWidget::mouseMoveEvent(QMouseEvent *MouseEvent)
{
    if(MouseEvent->globalPos() == mMousePos)
    {
        mPreviousPos = mapFromGlobal(mMousePos);
        return;
    }
    else
    {
        QCursor::setPos(mMousePos);
    }
    QPoint DeltaPos = MouseEvent->pos() - mPreviousPos;
    // Use DeltaPos to move my rotary
    mPreviousPos = MouseEvent->pos();
}

Essentiellement, chaque fois que la souris est déplacée, le changement est calculé, puis le curseur est ramené à la position de pression initiale (il ne peut donc jamais sortir de l'écran). Les if en haut de la page permet de s'assurer que la position de la souris n'est pas continuellement ramenée à la position d'origine.

Cela fonctionne bien sur les appareils à écran non tactile, mais pas sur les appareils à écran tactile, QCursor::setPos() ne fonctionne pas car je ne peux pas programmer la position d'un doigt sur un écran !

Je n'ai pas trouvé de solution qui réponde à toutes les exigences que j'ai décrites. S'il existait un moyen de détecter si l'utilisateur se sert d'un écran tactile, cela pourrait être corrigé, mais je n'ai trouvé aucune fonction de ce type dans Qt.

0voto

Ilya Kobelevskiy Points 3944

Au lieu d'essayer de forcer la souris à atteindre la position de clic, vous pouvez vérifier si la souris est sur le bord ou au-delà du bord, et si c'est le cas, utiliser un incrément constant pour le delta (dernier mouvement) :

void RotaryWidget::mouseMoveEvent(QMouseEvent *MouseEvent)
{
    QPoint DeltaPos;
    if(!isInsideWindow(MouseEvent))
    {
       DeltaPos = mPrevDeltaPos;
    }
    else
    {
       DeltaPos = MouseEvent->pos() - mPreviousPos;
       mPrevDeltaPos = DeltaPos;
       // Use DeltaPos to move my rotary
       mPreviousPos = MouseEvent->pos();
     }
}

EDIT :

Une autre option consisterait à calculer le DeltaPos sur la base des coordonnées globales de la souris plutôt que sur la base des coordonnées locales relatives à la fenêtre 0 - étant donné que seule la différence entre deux coordonnées de la souris est intéressante, la position n'a pas besoin d'être liée à la fenêtre. Dans ce cas, le widget fonctionnerait comme prévu à la fois pour les écrans tactiles et les écrans à souris - quelle que soit la position du curseur par rapport au cadre de la fenêtre, les mêmes mouvements de la souris/du doigt modifieraient l'orientation de la même manière.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X