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

 C++ Discussion :

Calback et événements : quel lien(s) entre ces 2 notions ?


Sujet :

C++

  1. #1
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut Calback et événements : quel lien(s) entre ces 2 notions ?
    Je comprends bien la notion d'événement, et j'utiilse souvent les callback des librairies.

    En revanche quand je dois concevoir une architecture, je bute toujours sur ces 2 notions : je me demande toujours si je dois créer un événements et son écouteur, ou une callback, ou des siganl/slot... ?

    Bref c'est le brouilllard.
    Pouvez vous m'aider à distinguer ces termes ?

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 400
    Points : 23 777
    Points
    23 777
    Par défaut
    Citation Envoyé par ttone Voir le message
    Je comprends bien la notion d'événement, et j'utiilse souvent les callback des librairies.

    En revanche quand je dois concevoir une architecture, je bute toujours sur ces 2 notions : je me demande toujours si je dois créer un événements et son écouteur, ou une callback, ou des siganl/slot... ?

    Bref c'est le brouilllard.
    Pouvez vous m'aider à distinguer ces termes ?
    Sur quelle plate-forme ? Même si tout ces concepts sont généraux, c'est surtout en fonction de cela qu'on utilisera plus les uns que les autres.

    Un « écouteur » est un objet qui se met à l'écoute d'un événement particulier. Donc pour cela, il faut qu'il y ait une file d'événements, et quelque chose à appeler lorsque l'événement surveillé survient.

    La seule différence, de mon propre point de vue, est qu'en général, un écouteur est un objet qui respecte une interface prédéfinie. La boucle principale sait alors à l'avance quelle méthode appeler. Il n'en reste pas moins que cette méthode est en elle-même une fonction de call-back (l'objet se déclare auprès d'un tiers, qui le « rappelle » en temps voulu), même si tu n'as pas eu besoin de la spécifier explicitement.

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 400
    Points : 23 777
    Points
    23 777
    Par défaut
    Citation Envoyé par ttone Voir le message
    Calback et événements : quel lien(s) entre ces 2 notions ?
    Pour répondre à cette question là en particulier : tu vas généralement avoir besoin d'une fonction de call-back pour réagir à des événements. C'est encore ce qu'il y a de plus simple.

    Cependant, on utilise des fonctions de call-back dans bien d'autres cas de figures : typiquement les tris, où la fonction qui embarque l'algo de tri proprement dit rappelle ta fonction pour faire une comparaison. Cette façon de faire te permet de trier n'importe quel type d'objets, mais il n'y pas de notion d'événements dans ce processus. Juste une bête boucle dont les appels sont prédictibles.

  4. #4
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Il y a au moins trois concepts:
    - des événements qui doivent être traîtés, donc par un seul destinataire, même si celui-ci peut n'être déterminé que par un pattern de chain of responsability; l'événement lui-même est souvent, mais pas toujours, réifié par l'utisation du pattern command.
    - le pattern publisher/observer où les observeurs peuvent naturellement être plusieurs. On peut aussi appeler événements les notifications qu'ils recoivent.
    - les callbacks sont des fonctions qu'on passe pour qu'elles soient appelées par après. C'est un mécanisme d'assez bas niveau qui peut servir entre autres pour implémenter les deux patterns ci-dessus.

  5. #5
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    Merci, je commence àà bien mieux cerner l'ensemble.
    - les callbacks sont des fonctions qu'on passe pour qu'elles soient appelées par après. C'est un mécanisme d'assez bas niveau qui peut servir entre autres pour implémenter les deux patterns ci-dessus.
    Le wikipedia des callbacks est assez bien :
    http://en.wikipedia.org/wiki/Callback_function

  6. #6
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    Pouvez vous m'aider sur un cas concret ? J'ai du mal

    J'ai 3 classes :
    * Ampli.class
    * Guitare.class
    * Jack.class

    Le jack se plugge sur l'ampli et sur la guitare.
    Le tout sont des éléménent représentés graphiquement.

    Ces 3 classes sont instanciées dans le main.

    L'objectif est le suivant : lorsque l'utilisateur déplace la guitare ou l'ampli, le jack doit être redessiné de manière à maintenir la connection.

    Guitare et ampli ont une fonction callback pertinente : moved()

    J'aimerai pouvoir faire réagir mon jack à l'appel de cette fonction.
    A la création , le jack se voit attribué 2 pointeurs : pGuitare, pAmpli.

    Que dois je faire conceptuellement parlant :

    1. pointer sur ampli et guitare dans Jack.class et créer un callback dans Jack,
    dans lequel j'assurerai le redimensionnement de mon jack grâce au donnée que je récupère sur guitare et ampli ?

    2. pointer sur le jack depuis Ampli.class et Guitar.class, et assurer son repaint depuis ces objets ?


    J'en suis à la solution 1 : elle me semble plus pertinente, en tous cas plus claire. Mais relier un callback de A sur un callback de B... vous auriez une bouée ?...

  7. #7
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    De prime abord, je dirais que tu n'a même pas besoin d'avoir un pointeur de type ampli ni de type guitare de ta classe jack...

    Tu pourrais te contenter d'une fonction surchargée (un exemplaire qui reçoit une référence constante de type guitare et l'autre qui reçoit une référence constante de type ampli), que tu nommerais éventuellement d'un nom un peu plus pertinent que "redraw()" et qui serait appelée par tes méthodes moved...

    Ce serait alors la guitare et l'ampli qui auraient un pointeur vers la prise jack, en somme, afin de pouvoir appeler redraw(*this)

    Pour moi, l'idée est que, comme on sait pertinemment quand exactement la fonction devra être appelée, il n'y a pas vraiment lieu de gérer cela par événement ou callback d'aucune sorte

  8. #8
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    C'est exactement ce que j'ai fait finalement...
    Merci koala.

    comme disait Einstein :
    "faites simple, aussi simpe que possible, mais pas plus"

  9. #9
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    En revanche, pour créer les jacks, l'interaction graphique telle que :
    * cliquer sur la guitare
    * tirer jusqu aà l'ampli
    * décliquer sur l'ampli

    je vais devoir envisager des callbacks, dès le moment où il y aura plusieurs amplis et plusieurs guitare;

    Là je crois que ca rentre dans l'exemple même de wikipedia.
    (éciter un for, l'asynchronisme...)

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Pourquoi

    Soit tu te dis qu'une guitare ne peut être connectée qu'à un seul ampli et inversément, et tu dois "simplement" prévoir le fait de maintenir en mémoire plusieurs guitares et ampli, soit tu te dis qu'une guitare peut etre connectée à plusieurs ampli et inversément, et tu dois donc aussi prévoir un vecteur ou une liste de prise jack pour les ampli et les guitares.

    Mais, quoi qu'il en soit, une prise jack ne pourra jamais être connectée qu'à zero ou une guitare (ou ampli)...

    Et, dans ce cas, on peut alors effectivement envisager de placer un pointeur sur guitare /ampli (idéalement, un pointeur de la classe mère des deux éléments) comme membre de la classe jack.

    Mais le pattern visiteur (ou la prise jack est l'objet visité et la guitare / l'ampli est le visiteur) - éventuellement adpaté - est tout à fait ce que tu recherche dans le cadre de la situation la plus complexe

    Au final, tu devrait gérer, au pire, les listes
    • de guitares
    • d'ampli
    • de prises jack
    et tu aurais des événement adaptés (onClick,onDrag, onDrop, par exemple) pour tous ces éléments, mais s'appliquant toujours sur un élément particulier, il "suffit" d'appeler la méthode qui va bien de l'élément en question

    La présence de callback n'apparaissant que dans la GUI, mais absolument pas au niveau des différentes classes envisagées (guitare, ampli et prise jack)

  11. #11
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    soit tu te dis qu'une guitare peut etre connectée à plusieurs ampli et inversément, et tu dois donc aussi prévoir un vecteur ou une liste de prise jack pour les ampli et les guitares.
    C'est ce que j'ai fais, je n'ai pas de bijectivité entre ampli et guitare.

    Mais le pattern visiteur (ou la prise jack est l'objet visité et la guitare / l'ampli est le visiteur) est tout à fait adapté à la situation la plus complexe
    En effet, merci, ca va dans le bon sens.

    La présence de callback n'apparaissant que dans la GUI
    tout à fait, ce qui me rassure c'est que faire un callback est plus accessible que je ne le craignais.

    Merci, tu as parfaitement ciblé mon problème

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 581
    Points
    41 581
    Par défaut
    Citation Envoyé par ttone Voir le message
    La présence de callback n'apparaissant que dans la GUI
    tout à fait, ce qui me rassure c'est que faire un callback est plus accessible que je ne le craignais.
    Attention, ceci est le cas du projet et non une généralité.
    Un appel à une fonction de tri peut avoir lieu n'importe où, par exemple, et comme dit plus haut, beaucoup de fonctions de tri acceptent une fonction en callback pour comparer...

  13. #13
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    oui tout à fait...

    d'ailleurs j'envisage des callback événementiel, et pas de tri, m^me si ca revient à mon avis à des tris sur la boucle d'événement...

    A ce propos, vous semble t il compliqué a priori d'appeler un mouseDown à partir du mouseDown d'une autre classe ?

    Par exemple : lorsque je clique sur un ampli, j'ai déjà une callback qui spécifie au programme quel ampli est cliqué. NB : c'est le programme (main) qui génère les jacks (cf plus haut)

    Mon API pose le problème suivant : un click sur un ampli n'est pas intercepté par le fond, c'est à dire le "programme principal", ou Studio.class _studio, en l'occurence.

    D'où ma question sur les mouse events.
    Mon API permet de modifier un MouseEvent de facon à ce qu'il soit approprié à un autre composant graphique (x,y,etc.).
    Mais je préfère tenter par moi même.

    J'ai deux solutions en clair :

    1. créer un callback qui lit l'event loop globale et trie...
    2. appeler mouseDown de Studio.class via mouseDown d'Ampli.class

    Vous êtes toujours là ? merci, donc je vais clarifier en une phrase si possible :

    une callback du studio m'indique quel ampli est cliqué, et pourtant un ampli cliqué appelle un mouseClick() du studio...

    C'est de la conception en papier maché ca non ?...

  14. #14
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Là encore, le pattern visiteur semblerait pouvoir te convenir:

    Tout clique ne va s'appliquer que sur ta "feuille de papier" (la vue de ton studio, en réalité )

    C'est cette vue qui va tester la position à laquelle le clique s'effectue afin de voir si il doit être relié à l'un des objet que la vue contient (guitare ou ampli).

    si, effectivement, le test trouve un objet sur lequel le clique peut être appliqué (car, autour des guitares et des ampli, il y a surtout énormément de vide ), la vue s'occupera de sélectionner l'élément en question.
    suivent ensuite les callback onDrag et onDrop, qui, dans le cas où un élément est sélectionné, appellera la méthode move() de la vue de l'élément sélectionné.

    Cette méthode move() appelant sans doute la méthode redraw() de la vue de l'élément.

    L'événement onDrop aura quant à lui pour effet de confirmer la position finale

    Ainsi, la classe "StudioView" pourrait être envisagée comme suit:
    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
    class StudioView
    {
        public:
            /* fonctions appelées depuis un callback relié à un menu */
            void createGuitare(int pox, int posy);
            void createAmpli(int posx, int posy);
            void eraseElement();
            void clearAll();
            /* fonction appelée par le clique sur la vue */
            void selectItem(int posx, int posy);
            /* fonction appelée par le callback onDrag */
            void moveItem(int posx, int posy);
            /* fonction appelée par le callback onDrop */
            void confirmItemPosition(int pox, int posy);
        private:
            /* pourrait être n'importe quel conteneur "qui va bien" */
            std::vector<ItemView*> allItems;
            /* l'élément sélectionné lors du clique (pointe sur l'élément
             * fraichement créé en cas de création
             */
            ItemView* selected;
    };
    Evidemment, tu aurais donc une arborescence proche de
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    class ItemView
    {
        public:
            /* toutes les méthodes qui peuvent permettre de tracer les objets 
             * dont, entre autre*/
            /* permet de faire disparaitre la trace de la vue */
            virtual void unDraw() = 0;
            /* permet de le faire retracer */
            virtual void draw() = 0;
            /* permet à la vue du studio d'appeler le comportement adéquat */
            virtual void doMove(StudioView*, int newposx, int newposy, 
                                int mouseStatus) = 0;
            /* des fonctions non virtuelles, car elles réagissent toujours de la 
             * meme  manière
             */
            int positionX() const;
            int positionY() const;
        private:
            /* les positions x et y de la vue (par exemple le coin supérieur 
             *gauche) 
             */
            int posx;
            int posy;
    };
    class GuitareView : public ItemView
    {
        public:
            /* spécialisation des méthodes en question */
        private:
            Guitare g;
    };
    class AmpliView : public ItemView
    {
        public:
            /* spécialisation des méthodes en question */
        private:
            Ampli a;
    };
    /* et, l'un dans l'autre, StudioView pourrait aussi hériter d'ItemView ;) */

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

Discussions similaires

  1. [XL-2010] Création automatique de graphes / TCD + Lien entre ces graphes
    Par Antoine3 dans le forum Excel
    Réponses: 2
    Dernier message: 08/08/2012, 14h05
  2. Réponses: 5
    Dernier message: 16/06/2010, 10h03
  3. Quel est la différence entre ces deux écritures ?
    Par TocTocKiéLà? dans le forum C++
    Réponses: 5
    Dernier message: 06/08/2007, 14h11
  4. Réponses: 4
    Dernier message: 27/07/2007, 16h39
  5. quel lien dois je faire entre mes classes ?
    Par condor_01 dans le forum Diagrammes de Classes
    Réponses: 8
    Dernier message: 01/03/2007, 23h17

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