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 :

Signaux et slots comme Qt


Sujet :

Qt

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de b Oo
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 179
    Par défaut Signaux et slots comme Qt, ou autres méthodes
    Bonjour,
    je réalise une application avec la SDL, et j'ai crée des boutons. Je voudrais que lorsqu'un bouton est pressé cela appelle la bonne fonction.

    La solution : Signals and Slots de Qt me parait intéressante et j'aimerais pouvoir l'implémenter.

    Pour cela, je pensais faire une classe Connecteur et une fonction connect qui prend l'objet emetteur, la méthode qui envoie le signal, l'objet recepteur, et la méthode qui doit recevoir le signal.

    Idée pour la classe Connecteur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    template <class Emetteur, class Recepteur>
    class Connecteur
    {
        Emetteur & emetteur;
        Connecteur & connecteur;
        // Et la problème je ne peux pas déclarer mes pointeurs sur des méthodes
        // car je peux avoir void, int, ...
    };
    De plus admettons que je puisse faire la déclaration de mes méthodes (c'est peux etre possible en s'inspirant de mem_fun), je voudrais un conteneur de pointeurs sur mes objets, et de pointeurs sur mes méthodes pour pouvoir y accéder de cette maniere :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // admettons que ce code marche
    Bouton bouton;
    Receveur receveur;
    connect(&bouton, &bouton::onCLic, &receveur, &Receveur::methode);
    onClic a le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void Bouton::onClic()
    {
        Connecteur::send(this, &Bouton::onClic);
    }
    et send :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void Connecteur::send(Emetteur & emetteur, PtrEMethode methode) // PtrEMethode est un typedef pour un pointeur de methode de emetteur
    {
        Recepteur * objet = connecteurs[emetteur][methode].first;
        PtrRMethode * methodeR =  connecteurs[emetteur][methode].second;
        objet->(*methodeR)();
    }
    Avec ce code je dois forcement avoir une methode qui n'a pas de parametres donc c'est très limité, mais bon le problème est que cette idée d'implémentation ne me parait pas réalisable.

    J'aimerais avoir votre avis, et savoir comment vous feriez pour implémenter ceci, ou s'il y a une meilleur méthode que celle utilisée par Qt faite le moi savoir.

    D'avance merci.

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Tu as jeté un oeil sur boost.signals ?

    MAT.

  3. #3
    Membre confirmé Avatar de b Oo
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 179
    Par défaut
    Je vais me pencher de ce pas sur le lien que tu viens de me donner Mat007.

    Merci !

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Je n'ai jamais compris comment on pouvait même avoir l'idée d'un truc comme le système de Qt.

    C'est simple, quand un événement se produit tu veux appeler un foncteur. Alors quand un événement se produit, appelle ce foncteur.
    Voilà, c'est tout.

    T'as juste besoin d'une manière unifiée de pouvoir stocker les différents types de foncteurs, et c'est boost::function.

  5. #5
    Membre confirmé Avatar de b Oo
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 179
    Par défaut
    Bonjour loufoque,
    amdettons que j'ai un bouton, je veux lui connecter une fonction, une méthode ou plusieurs, tu ferais comment ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Bouton monBouton;
    monBouton.connect(/* un foncteur */);
    monBouton.connect(/* un autre foncteur */);
    Admettons que le premier foncteur est crée a partir d'un void toto() et le deuxieme d'un int tata(int);
    Comment je declare le signal dans mon bouton ?

    De plus admettons que j'ai deux methodes auxquelles je dois connecter des foncteurs differents, comme je peux faire ?
    Avec un connect qui prend en parametre le signal que auquel je veux connecter ?

    Ce que je veux faire est-il réalisable avec boost ?

    Merci.

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Un exemple de ce que l'on peut faire :

    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
    40
    41
    42
    43
    44
    45
    46
    class Bouton
    {
    public :
     
        void OnClick(boost::function<void ()> F)
        {
            myOnClick = F;
        }
     
        void OnMouseMove(boost::function<void (int, int)> F)
        {
            myOnMouseMove = F;
        }
     
    private :
     
        void Update()
        {
            if (... detection du click souris ...)
                myOnClick();
     
            if (... detection du mouvement souris en (X, Y) ...)
                myOnMouseMove(X, Y);
        }
     
        boost::function<void ()> myOnClick;
        boost::function<void (int, int)> myOnMouseMove;
    };
     
    void OnMouseMove(int X, int Y)
    {
        std::cout << "Déplacement de la souris sur le bouton en " << X << ", " << Y << std::endl;
    }
     
    struct ClickHandler
    {
        void OnClick()
        {
            std::cout << "Click sur le bouton" << std::endl;
        }
    };
    ClickHandler Click;
     
    Bouton monBouton;
    monBouton.OnClick(boost::bind(&ClickHandler::OnClick, Click));
    monBouton.OnMouseMove(boost::bind(&OnMouseMove));
    [Code sorti à la volée sans vérification]

  7. #7
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par loufoque
    C'est simple, quand un évènement se produit tu veux appeler un foncteur. Alors quand un évènement se produit, appelle ce foncteur.
    Voilà, c'est tout.

    T'as juste besoin d'une manière unifiée de pouvoir stocker les différents types de foncteurs, et c'est boost::function.
    En gros, boost::signal, c'est ce que tu dis avec quelques détails supplémentaires, de tête :
    - La possibilité de gérer n foncteurs pour un signal (y compris en gérant la combinaison des valeurs de retour)
    - Une sorte de gestion automatique des durées de vie, qui efface les objets de connections quand un objet possédant un signal où un slot est détruit.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  8. #8
    Membre confirmé Avatar de b Oo
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 179
    Par défaut
    Je m'explique, je veux savoir si c'est possible de faire ceci avec une seule classe plutôt que 2.
    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
    40
    41
    42
    43
    44
    45
    46
    47
     
    class Bouton1
    {
        public:
          void onEvent(Event & event)
          {
             if(/* clic */)
               onClic();
          }
          void connect(boost::function<void ()>f)
          {
             onClic = f;
          }
     
        private:
          boost::function<void ()> onClic;
    };
     
    class Bouton2
    {
        public:
          void onEvent(Event & event)
          {
             if(/* clic */)
               onClic(event.x, event.y);
          }
          void connect(boost::function<void (int, int)>f)
          {
             onClic = f;
          }
     
        private:
          boost::function<void (int, int)> onClic;
    };
     
    void affiche(int x, int y)
    {
        std::cout << "Clic a la position : " << x << ',' << y << ".\n";
    }
     
    /* J'ai une instance app de Application qui a une methode quit() */
    Application app;
    Bouton1 bouton1;
    bouton1.connect(boost::bind(&Application::quit(), app);
     
    Bouton2 bouton2;
    bouton2.connect(boost::bind(&affiche);
    Citation Envoyé par Laurent Gomila
    Si le paramètre est connu au moment où tu connectes le slot, tu peux le spécifier à boost::bind.
    Ici, c'est comme si je faisais un bind1st ou bind2nd ?

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

Discussions similaires

  1. Signaux et slots avec Qt4
    Par dourouc05 dans le forum Téléchargez
    Réponses: 0
    Dernier message: 01/11/2010, 22h23
  2. [Qt4] Signaux et Slot
    Par gentox dans le forum Qt
    Réponses: 9
    Dernier message: 25/01/2007, 18h35
  3. Réponses: 10
    Dernier message: 09/10/2005, 22h33

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