IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Qt Discussion :

Récupération de l'état d'une touche modifiée par l'event d'un autre widget


Sujet :

Qt

  1. #1
    Membre confirmé
    Avatar de betsprite
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    472
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 472
    Points : 528
    Points
    528
    Par défaut Récupération de l'état d'une touche modifiée par l'event d'un autre widget
    Bonjour tout le monde,

    je suis actuellement confronté à un problème de gestion globale d'événements à l'intérieur de mon application. Je m'explique :

    J'ai en partie dans ma fenêtre principale des zones de saisie avec à côté deux boutons (incrémentation/décrémentation de la valeur de la zone de saisie avec un pas par défaut de 1). Lorsque la touche SHIFT du clavier est enfoncée, le pas passe à 10. Jusqu'ici le comportement est simple.

    Je ré-implémente donc dans mes boutons les méthodes KeyPressEvent() et KeyReleaseEvent() pour affecter respectivement les valeurs true et false à ma variable membre isShiftPressed.

    Seulement, imaginons maintenant que je veuille enfoncé shift avant de cliquer sur le bouton. Je m'aperçois alors que le pas est toujours de 1, le bouton n'ayant pas eu le focus au moment de l'appui sur SHIFT et la méthode KeyPressEvent() du bouton n'ayant donc pas été appelée.

    L'événement doit donc être géré de façon plus globale dans mon application, d'autant plus que ce n'est surement pas le seul composant qui aura besoin de connaître l'état de cette touche.

    Je vois alors plusieurs solutions mais je souhaiterais avoir votre avis sur la meilleure à utiliser (qui ne fait pas forcément parti de l'une d'entre elles :p ) :

    1) Gérer les événements "globaux" au niveau de windows (appli windows ici mais cette méthode me paraît lourde).

    2) Utiliser une variable globale isShiftPressed pour que l'état soit connu partout et modifier dans les widgets sa valeur via les événements KeyPressEvent() et KeyReleaseEvent() .

    3) Utiliser un eventFilter pour filtrer les événements (événement qui serait a priori inclus dans la fenêtre principale mais cela impliquerait que celle-ci doit toujours être le widget focus sinon la méthode n'est plus appelée, donc que si je clic sur un bouton, Qt lui donnant par défaut le focus, je dois forcer le focus pour le rendre à ma fenêtre principale... ça fait un peu trop bidouille à mon goût ^^) (Edit : ce dernier comportement peut en fait être évité grâce à la méthode setFocusPolicy(Qt::NoFocus) pour garder le focus sur la fenêtre principale mais j'aurais besoin d'avoir le focus sur un certain nombre de widget pour faire appel à leurs événements... Dans ce cas là, si ces widgets ont le focus, que je maintiens shift (donc que la fenêtre principale ne met pas à jour l'enfoncement de la touche), et que je viens cliquer sur un bouton, je me retrouve au point de départ).

    4) Reprendre l'idée du 3) mais en ré-implémentant plutôt event(). Mais le 3) et 4) semble être inapproprié ici au final parce que j'ai besoin de permettre le focus des composants intérieurs (sinon appel à mouseMoveEvent() d'un widget impossible non? ou alors redistribution possible mais ça risque d'être lourd de toujours tester la position du curseur pour voir à quel composant on veut s'adresser et donc quel événement on veut véritablement appelé..)

    J'ai l'impression que je n'ai pas trouvé encore la meilleure solution à ce problème. Je suis à l'écoute de tous vos conseils

    Merci beaucoup !

  2. #2
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Bonjour,

    Si vous n'aviez qu'un seul widget affecté par ce comportement, je vous aurai proposé de faire un grabKeyboard sur le widget. Si ce n'est pas le cas, une globale avec un eventFilter() pourrait être intéressant (avec toujours de l'event->ignore() pour ne pas casser les widgets utilisant le shift).

    EDIT: vous avez aussi http://qt-project.org/doc/qt-4.8/qap...boardModifiers.

    Bonne continuation,
    Amnell.
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

  3. #3
    Membre confirmé
    Avatar de betsprite
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    472
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 472
    Points : 528
    Points
    528
    Par défaut
    Bonjour Amnell et merci pour votre réponse

    Tout d'abord, oui, il y aura surement plusieurs widgets qui auront besoin d'avoir ce comportement ou un comportement similaire.

    Concernant la variable globale avec l'eventFilter, je devrais donc bien conserver le focus uniquement sur le widget ré-implémentant cette méthode pour qu'elle soit appelée à chaque événement non? Si c'est le cas, j'aurai toujours le problème de devoir faire des tests assez lourd sur la position de mon curseur pour voir quel widget je survole et donc sur quel widget je souhaite récupérer les événements...

    Je ne connaissais pas du tout keyboardModifiers() ! ça a l'air d'être ce que je veux. Il y a juste un petit soucis que j'essaie de régler : Lorsque j'enfonce shift une fois ça marche, mais lorsque je relâche ensuite, keyboardModifiers me renvoit toujours le flag correspond à shift pressed(En gros même si j'apui et relâche juste après le shift sans garder le bouton enfoncé, keyboardModifiers() renvoit un comportement shift pressed). Il n'y a pas de gestion de relâchement ? Je dois gérer ça dans les méthodes keyPressEvent/keyReleaseEvent des widgets de mon interface pour qu'il "refresh" le dernier état du clavier ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
      Qt::KeyboardModifiers test = QApplication::keyboardModifiers();
     
      qDebug() << "test : " << test;
     
      if (test = Qt::ShiftModifier)
    {
    // rentre à tous les coups après avoir enfoncé shift une fois et même en relâchant après
    }
    Merci

  4. #4
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Citation Envoyé par betsprite Voir le message
    Je ne connaissais pas du tout keyboardModifiers() ! ça a l'air d'être ce que je veux. Il y a juste un petit soucis que j'essaie de régler : Lorsque j'enfonce shift une fois ça marche, mais lorsque je relâche ensuite, keyboardModifiers me renvoit toujours le flag correspond à shift pressed(En gros même si j'apui et relâche juste après le shift sans garder le bouton enfoncé, keyboardModifiers() renvoit un comportement shift pressed). Il n'y a pas de gestion de relâchement ? Je dois gérer ça dans les méthodes keyPressEvent/keyReleaseEvent des widgets de mon interface pour qu'il "refresh" le dernier état du clavier ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
      Qt::KeyboardModifiers test = QApplication::keyboardModifiers();
     
      qDebug() << "test : " << test;
     
      if (test = Qt::ShiftModifier)
    {
    // rentre à tous les coups après avoir enfoncé shift une fois et même en relâchant après
    }
    Merci
    Avec un seul égal aussi, ça ne va pas le faire. Même avec deux en réalité :

    The KeyboardModifiers type is a typedef for QFlags<KeyboardModifier>. It stores an OR combination of KeyboardModifier values.
    On doit donc tester le flag avec ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int test = QApplication::keyboardModifiers();
     
    if (test & Qt::ShiftModifier)
        doSomething(test);
    EDIT : la doc dit également :

    The current state is updated sychronously as the event queue is emptied of events that will spontaneously change the keyboard state (QEvent::KeyPress and QEvent::KeyRelease events).
    Donc un QCoreApplication::processEvent() avant l'appel devrait régler le problème.

    R-EDIT : si vous tournez avec Qt 4.8, vous avez également QApplication::queryKeyboardModifiers() qui retourne les modificateurs actuels (pas besoin de faire la manipulation donnée ci-dessus).
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

  5. #5
    Membre confirmé
    Avatar de betsprite
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    472
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 472
    Points : 528
    Points
    528
    Par défaut
    Avec un seul égal aussi, ça ne va pas le faire.
    Effectivement ça fonctionne tout de suite moins bien
    Après je ne savais pas vraiment comment manipuler le flag qui me retournait une valeur différente du Qt::ShiftModifier que je m'attendais à recevoir. Mais finalement une convertion semble avoir été faite.

    Même avec deux en réalité
    Bizarrement j'ai essayé seulement avec deux signes égal et ça a l'air de fonctionner correctement. Encore mieux, je n'ai même pas besoin de faire un processEvent(). Lorsque je relâche le bouton le test n'est effectivement plus vérifié..

    Toutefois, autant bien faire les choses. Je ne comprends d'ailleurs pas bien le teste que vous faites :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (test & Qt::ShiftModifier)
    vous vouliez mettre "&&" ?

    D'après la documentation justement :
    It stores an OR combination of KeyboardModifier values.
    Or ici, je n'ai qu'un seul keyboardModifier, ça doit être pour cette raison que ça fonctionne dans mon cas avec un simple test d'égalité. Après, il est vrai que si on a une liste de keyboardModifiers, votre syntaxe fonctionnera contrairement à la mienne.

    Enfin, je ne vois pas trop dans quelle condition il serait utile de faire queryKeyboardModifiers() étant donné que même avec keyboardModifier, il ne semble pas y avoir besoin de faire un processEvent()

  6. #6
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Citation Envoyé par betsprite Voir le message
    Toutefois, autant bien faire les choses. Je ne comprends d'ailleurs pas bien le teste que vous faites :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (test & Qt::ShiftModifier)
    vous vouliez mettre "&&" ?

    D'après la documentation justement : Or ici, je n'ai qu'un seul keyboardModifier, ça doit être pour cette raison que ça fonctionne dans mon cas avec un simple test d'égalité. Après, il est vrai que si on a une liste de keyboardModifiers, votre syntaxe fonctionnera contrairement à la mienne.

    Enfin, je ne vois pas trop dans quelle condition il serait utile de faire queryKeyboardModifiers() étant donné que même avec keyboardModifier, il ne semble pas y avoir besoin de faire un processEvent()
    Je voulais dire que deux = ne fonctionneraient pas plus si on appuie sur Alt en même temps, par exemple. C'est une combinaison OR, donc il faut checker la valeur avec l'opérateur binaire "&" (oui, un seul, je n'ai pas fait de faute de frappe) qui va checker la présence du flag Qt::ShiftModifier dans test (qui peut contenir plusieurs flags) et retourner 0 ou 1.

    Pour le queryKeyboardModifier, c'est la même fonction que l'autre, sauf qu'elle retourne des valeurs "à jour" par rapport à la boucle d'événements. Si votre application pompe le process au point que les events se mettent en file d'attente, keyboardModifiers() retournera des valeurs périmées (sauf à appeler QCoreApplication::processEvent() qui va forcer les événements en file à être traités avant d'appeler la fonction).
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

  7. #7
    Membre confirmé
    Avatar de betsprite
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    472
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 472
    Points : 528
    Points
    528
    Par défaut
    l'opérateur binaire & (oui, un seul, je n'ai pas fait de faute de frappe)
    Effectivement ! Désolé pour la question, j'ignorais qu'il était possible d'utiliser un "&" seul comme opérateur, à vrai dire, je ne m'étais jamais posé la question

    Concernant queryKeyboardModifier(), je saisie mieux maintenant son intérêt !

    Merci beaucoup pour votre aide Amnell, vos réponses sont très claires

  8. #8
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    N'oubliez pas le
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [PHP 5.2] récupération de l'état d'une checkbox avec un formulaire ?
    Par [ZiP] dans le forum Langage
    Réponses: 2
    Dernier message: 16/01/2009, 10h21
  2. [C# 3.0] Connaître l'état d'une touche.
    Par GilProd dans le forum C#
    Réponses: 9
    Dernier message: 23/02/2008, 22h48
  3. Récupération de l'état d'une scrollbar
    Par Zorgblub dans le forum GTK+ avec C & C++
    Réponses: 2
    Dernier message: 15/11/2007, 21h22
  4. Récupération d'un appui sur une touche du clavier
    Par eddie5150 dans le forum MFC
    Réponses: 2
    Dernier message: 09/05/2007, 14h40
  5. connaitre état d'une touche clavier
    Par orelero dans le forum AWT/Swing
    Réponses: 3
    Dernier message: 13/06/2006, 18h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo