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 :

Actions avec QStateMachine


Sujet :

Qt

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2012
    Messages : 4
    Par défaut Actions avec QStateMachine
    Bonjour,

    Je cherche à utiliser correctement les outils de QStateMachine pour gérer ma machine à état. Ci-joint un exemple de machine simple, où
    - E1, E2, E3 sont les 3 états
    - C1... C6 sont les conditions pour déclencher les transitions
    - A1... A6 sont les actions à réaliser sur ces transitions

    Mon problème est le suivant : comment réaliser des actions complexes sur les transitions ?

    Je cherche par exemple à dessiner quelque chose, déplacer un objet à l'écran, envoyer quelque chose par le réseau...

    Dans l'exemple de la documentation Qt, dans la partie "Doing Useful Work", il y a deux propositions :

    - utiliser "assignProperty" : possible seulement pour les actions faciles comme dans leur exemple changer le texte d'un bouton, mais il n'y a pas de propriété pour toute action
    - utiliser les signaux "entered() et exited()" et les connecter à une fonction qui fait l'action désirée : sympa mais c'est lié à l'état seulement et pas à la transition. Dans mon exemple, je ne fais pas la même chose si je quitte E1 pour aller vers E2 ou E3, de même que je ne fais pas la même chose si j'arrive dans E2 en provenance de E1 ou E3.

    J'ai trouvé sur internet des propositions de sous-classer les objets transition (QSignalTransition), et de faire l'action dans sa méthode "onTransition()" mais ça me semble bien lourd pour quelque chose d'aussi simple...

    Merci d'avance !
    Images attachées Images attachées  

  2. #2
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Salut
    Citation Envoyé par Quemm Voir le message
    J'ai trouvé sur internet des propositions de sous-classer les objets transition (QSignalTransition), et de faire l'action dans sa méthode "onTransition()" mais ça me semble bien lourd pour quelque chose d'aussi simple...

    Merci d'avance !
    Pourquoi ne pas te créer ton propre QSignalTransition qui emet un signal dans le onTransition ?

    La condition de tes transition dépend unique de signaux?

    Veux tu utiliser les fonctionnalités de C++11?

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2012
    Messages : 4
    Par défaut
    Citation Envoyé par yan Voir le message
    Salut

    Pourquoi ne pas te créer ton propre QSignalTransition qui emet un signal dans le onTransition ?

    La condition de tes transition dépend unique de signaux?
    Ça me plait, c'est en effet une possibilité. Ce qui m'étonne c'est de devoir justement se créer ces fonctions-là alors que ça me semble basique et je m'attends à avoir ces outils plus directement avec le framework State Machine.

    Pour info l'exemple que j'ai trouvé avec les actions (calcul, printf) présentes dans les méthodes "onTransition()".

    Citation Envoyé par yan Voir le message
    Veux tu utiliser les fonctionnalités de C++11?
    Je ne connais pas les fonctionnalités spécifiques de C++ 11 donc je ne peux pas répondre. Tu penses à quelque chose de précis qui correspond à mon cas ?

  4. #4
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Ça me plait, c'est en effet une possibilité.
    http://doc.trolltech.com/4.7-snapsho...html#triggered

    je l'avais oublié celui là


    Je ne connais pas les fonctionnalités spécifiques de C++ 11 donc je ne peux pas répondre. Tu penses à quelque chose de précis qui correspond à mon cas ?
    Oui au lambda et au std::function.


    Pour un projet j'ai basé le fonctionnement de thread sur des events injectés dans une StateMachine. Pour simplifié le développement j'ai créé des events et des transitions exploitant les std::functional. Pour customiser ces classes, j'utilise des lambda.

    C'est trés puissant

  5. #5
    Responsable Qt & Livres


    Avatar de dourouc05
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2008
    Messages
    26 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2008
    Messages : 26 772
    Par défaut
    Citation Envoyé par yan Voir le message
    C'est trés puissant
    Et ça mériterait un article, non ?
    Vous souhaitez participer aux rubriques Qt (tutoriels, FAQ, traductions) ou HPC ? Contactez-moi par MP.

    Créer des applications graphiques en Python avec PyQt5
    Créer des applications avec Qt 5.

    Pas de question d'ordre technique par MP !

  6. #6
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par dourouc05 Voir le message
    Et ça mériterait un article, non ?
    Avec l'ajout des classes dans QExtend
    ... Mais faudrais que je termine celui sur les thread avant

    Mais pourquoi pas.

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2012
    Messages : 4
    Par défaut
    Citation Envoyé par yan Voir le message
    Ça existe déjà en effet.
    Cependant je ne suis finalement pas si certain que c'est ce qui m'intéresse : je veux réagir aux évènements (signaux) que je reçois et non aux transitions. Il peut y avoir énormément de transitions dès que la machine à état grandit un peu.

    Ce qui me pose problème avec l'utilisation de QStateMachine c'est que sur réception d'un évènement (ici réception d'un signal émis par une autre classe), je veux à la fois, dans l'ordre suivant :
    1) faire quelque chose, qui est fonction de l'état dans lequel je suis quand je reçois l'évènement
    2) faire évoluer la machine à état

    Ce qui peut se traduire par un code qui ressemble à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // 1)
    QObject::connect(myEventSenderObject,SIGNAL(myEvent()),this,handleEvent());
    // 2)
    E1->addTransition(myEventSenderObject,SIGNAL(myEvent()),E2);
    Or avec le fonctionnement de QStateMachine, je passe à E2 avant d'exécuter handleEvent(), et dans cette méthode je ne peux plus savoir que j'étais en E1.

    La solution à laquelle je pense est de créer des signaux "jumeaux" des signaux reçus, que j'émets une fois ceux reçus de l'extérieur traités, ce qui me permet de changer d'état après avoir traité l'action. Ça fonctionne sur un petit exemple, mais ça ne me semblait pas être la bonne utilisation de QStateMachine.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 1)
    QObject::connect(myEventSenderObject,SIGNAL(myEvent()),this,handleEvent());
    // 2)
    E1->addTransition(this,SIGNAL(myEventProcessed()),E2);
     
    // Et dans ma méthode handleEvent()
    myClass::handleEvent(){
    switch (states) {
    case E1:
    // do something
    case E2:
    // do something else
    // ...
    }
    emit myEventProcessed();
    }

  8. #8
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Or avec le fonctionnement de QStateMachine, je passe à E2 avant d'exécuter handleEvent(), et dans cette méthode je ne peux plus savoir que j'étais en E1.
    Pourquoi handleEvent serait exécuté après le passage en E2 ?
    tu utilise la même instance de QSignalTransition sur plusieurs addTransition ?

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2012
    Messages : 4
    Par défaut
    Citation Envoyé par yan Voir le message
    Pourquoi handleEvent serait exécuté après le passage en E2 ?
    C'est ce que j'avais observé, tout du moins pas avec des signaux mais des QMouseEvent.
    Voici en gros le code avec lequel j'avais testé ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    TestMachine::TestMachine(QWidget *parent):
    {
    // Déclaration de la machine à état
    // ...
    // Si etat Pressed et je relâche la souris alors je passe en état Init
    QEventTransition *eventTransition2 = new QEventTransition(this, QEvent::MouseButtonRelease);
    eventTransition2->setTargetState(Init);
    Pressed->addTransition(eventTransition2);
    }
     
    // Réimplémentation de mouseReleaseEvent
    void TestMachine::mouseReleaseEvent(QMouseEvent *event)
    {
        // Si je suis en état Pressed
        if (machine->configuration().contains(Pressed))
        {
        // Do something
        }
        else
        {
        // Do something else
        }
    }
    Le reste de la machine fonctionne, ici je montre le bout de code qui déclare la transition de l'état "Pressed" à l'état "Init" quand je relâche la souris, et la réimplémentation de la fonction qui capte le même évènement pour faire quelque chose quand je reçois cet évènement et que je suis dans l'état "Pressed".
    Eh bien ici ça ne fonctionnait pas : ma machine passait en état "Init" avant que je le veuille.
    J'ai un QEventTransition au lieu d'un QSignalTransition mais je ne crois pas que ça soit ça qui change le comportement de la machine à état.

    C'est cet exemple que j'avais modifié pour émettre un signal perso :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    TestMachine::TestMachine(QWidget *parent):
    {
    // Déclaration de la machine à état
    // ...
    // Si etat Pressed et je relâche la souris alors je passe en état Init
    Pressed->addTransition(this,SIGNAL(widgetMouseReleaseEvent(QMouseEvent*)),Init);
    }
     
    void TestMachine::mouseReleaseEvent(QMouseEvent *event)
    {
        // Si je suis en état Pressed
        if (machine->configuration().contains(Pressed))
        {
        // Do something
        }
        else
        {
        // Do something else
        }
    emit widgetMouseReleaseEvent(event);
    }
    Et ça fonctionnait comme je voulais.

    Citation Envoyé par yan Voir le message
    tu utilise la même instance de QSignalTransition sur plusieurs addTransition ?
    Voir le deuxième extrait de code ci-dessus : je ne déclare pas explicitement mes objets QSignalTransition, j'ajoute les transitions dans la machine directement avec la méthode addTransition().

Discussions similaires

  1. repeter une action avec un timer
    Par blondelle dans le forum C++Builder
    Réponses: 30
    Dernier message: 24/10/2008, 01h25
  2. Requete Action avec parametre dans formulaire
    Par marie10 dans le forum IHM
    Réponses: 2
    Dernier message: 08/02/2006, 12h02
  3. Déclencher une action avec un chrono
    Par Oberown dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 20/09/2005, 14h22
  4. [JTextField] Déclencher une action avec la touche ENTER
    Par tchoukapi dans le forum Composants
    Réponses: 10
    Dernier message: 19/09/2005, 14h37
  5. Réponses: 4
    Dernier message: 27/04/2004, 14h45

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