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 :

Héritage de signaux : redéfinition possible ?


Sujet :

Qt

  1. #1
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 63
    Points : 51
    Points
    51
    Par défaut Héritage de signaux : redéfinition possible ?
    Bonjour,

    Je voudrais savoir si il est possible de surcharger/redéfinir un signal dans une classe fille.

    Je m'explique :
    Dans la classe QMenu, j'ai le signal hovered(QAction*) qui m'intéresse.
    Cependant j'ai fait une classe dérivée de QAction pour y ajouter des attributs et quelques fonctions.
    J'ai appelé cette classe SousMenu.

    Est-il possible d'avoir un signal du type hovered(SousMenu*) éventuellement en dérivant aussi la classe QMenu?

  2. #2
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2007
    Messages
    774
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mai 2007
    Messages : 774
    Points : 969
    Points
    969
    Par défaut
    Si ta classe SousMenu dérive de QAction, ça veut dire que ta classe SousMenu a toutes les propriétés de QAction + celles que tu as ajouté.

    Donc tu n'as rien à modifier, le signal marchera tout seul.

    TU peux faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monMenu.addAction(new SousMenu(blabla));
    ça marchera aussi.

    G.
    Un problème avec Qt ? Vous trouverez votre réponse ici : http://doc.trolltech.com/4.6/overviews.html
    En français (traduction réalisée par l'équipe Qt de DVP) : http://qt.developpez.com/doc/4.6/vues-d-ensemble/

  3. #3
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 63
    Points : 51
    Points
    51
    Par défaut
    Hello,
    Merci de répondre.
    Je fais bien comme tu as dis pour ajouter mon sous menu au menu.
    Seulement ensuite je voudrais connecter le clic et le survol souris de mes SousMenus à des slots.

    Logiquement, cette connexion se fait comme ça : (pour le survol)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    connect(un_Menu,SIGNAL(hovered(QAction*)),this,SLOT(cliqueSousMenu(QAction*)));
    Mais là le signal dépend de un_Menu.
    Je cherche à passer en paramètres mon SousMenu dans le connect comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    connect(un_Menu,SIGNAL(hovered(SousMenu*)),this,SLOT(cliqueSousMenu(SousMenu*)));
    Je cale un petit peu.
    J'ai voulu dériver la classe QMenu et surcharcher le signal "hovered" mais je ne sais pas trop comment m'y prendre...

    Si tu as déjà fait ça...

  4. #4
    Membre confirmé
    Avatar de haraelendil
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2004
    Messages
    283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2004
    Messages : 283
    Points : 533
    Points
    533
    Par défaut
    Tu n'as pas besoin de surcharger le signal, soit ton sous menu hérite de QMenu, et il va faire les choses comme le ferai un menu normal (donc tu connecte ton signal de la même façon), sinon tu crée une classe de toute pièce, et la c'est à toi de faire des emit(monSignal) quand tu veux que ton sous menu émette ce signal...

  5. #5
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 63
    Points : 51
    Points
    51
    Par défaut
    Alors comment retourner un attribut de mon SousMenu depuis le slot cliqueSousMenu() ?
    Je vous mets une partie de ma classe SousMenu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class SousMenu: public QAction
    {
    public:
        SousMenu(QString nom, QObject *parent):QAction(nom,parent=0){
        }
        //Accès aux attributs du SousMenu 
        void setMotCle(QString motCle);
        QString getMotCle();
     
    private:
        QString m_MotCle;
     
    };
    et le slot cliqueSousMenu()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void FenetrePrincipale::cliqueSousMenu(SousMenu* sMenu){
     
    //Affichage du mot clé de sous menu dans un QTextBrowser
    //sur la fenêtre principale. 
    this->visu->append(sMenu->getMotCle());
    }
    Si le slot cliqueSousMenu n'a pas un SousMenu en paramètre, il ne peut me retourner l'attribut m_MotCle.

  6. #6
    Membre confirmé
    Avatar de haraelendil
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2004
    Messages
    283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2004
    Messages : 283
    Points : 533
    Points
    533
    Par défaut
    Si c'est ton sousMenu qui émet le signal directement, tu peux récupérer un pointeur sur celui-ci grâce à QObject::sender()

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void FenetrePrincipale::cliqueSousMenu()
    {
    //Affichage du mot clé de sous menu dans un QTextBrowser
    //sur la fenêtre principale. 
    SousMenu* sMenu = qobject_cast<SousMenu*>(sender());
    if(sMenu == NULL) return;
    this->visu->append(sMenu->getMotCle());
    }

  7. #7
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 63
    Points : 51
    Points
    51
    Par défaut
    Oui ça j'avais vu.
    A la rigueur je peux faire envoyer le signal par le SousMenu et le caster ensuite même si ce n'est pas ce que je veux faire à la base.
    Donc pour répondre à la question du début on ne peut pas surcharger un signal.

    Et comme tu peux le voir, je ne mets pas le QOBJECT dans ma classe, je ne comprends pas trop son utilisation.
    Pour utiliser l'option que tu proposes je suis obligé de le faire.

    Quelles sont les différences avec ma classe d'origine si je rajoute ça?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class SousMenu: public QAction
    {
    Q_OBJECT // ajout ici par rapport à la classe d'origine
                   // Seule modification à effectuer? 
     
    public:
        SousMenu(QString nom, QObject *parent):QAction(nom,parent=0){
        }
    ...
    };

  8. #8
    Membre confirmé
    Avatar de haraelendil
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2004
    Messages
    283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2004
    Messages : 283
    Points : 533
    Points
    533
    Par défaut
    La macro Q_OBJECT est nécessaire si tu veux te servir des signaux / slots de ta classe, ainsi que les propriétés des QObjects

    plus d'info sur cette macro:
    article sur les méta-objets

  9. #9
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Bonjour à tous

    J'ai un peu de mal à comprendre...

    1. QMenu hérite de QWidget et représente un objet visible à l'écran. QAction par contre hérite directement de QObject et n'est pas sensé représenter un objet visible (et donc pas un sous menu en particulier). Donc pour créer un sous menu, tu dois hériter de QMenu et non de QAction

    2. Si tu veux créer un sous menu, tu peux simplement utiliser addMenu de QMenu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    QMenu * menu = new QMenu("mon menu");
    m->addAction(new QAction("action 1", menu);
    m->addAction(new QAction("action 2", menu);
    m->addAction(new QAction("action 3", menu);
    m->addAction(new QAction("action 4", menu);
    QMenu * sous_menu = new QMenu("mon sous menu");
    menu->addMenu(sous_menu);
    sous_menu->addAction(new QAction("sous menu 1", sous_menu));
    sous_menu->addAction(new QAction("sous menu 2", sous_menu));
    sous_menu->addAction(new QAction("sous menu 3", sous_menu));
    3. Comme indiqué dans la doc de QObject ("Warning: This function violates the object-oriented principle of modularity."), sender() ne respecte pas la conception objet et doit être évité (son utilisation indique en général un problème de conception)

    As tu une raison particulière de vouloir hériter de QAction pour ton sous menu (c'est à dire quels sont les caractéristiques de QAction que tu souhaites utiliser/hériter et quels sont celles que tu souhaites ajouter/modifier) ?

  10. #10
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 63
    Points : 51
    Points
    51
    Par défaut
    Merci beaucoup !
    J'ai cherché un article qui expliquait ça mais j'avais pas trouvé
    Je vais regarder ça tranquillement ce soir et si ça me convient je mettrai résolu.
    merci encore.

  11. #11
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 63
    Points : 51
    Points
    51
    Par défaut
    Salut gbdivers,

    Lors de mon clic souris sur un sousmenu (donc un QAction), je veux récupérer un motClé qui va conditionner tout l'affichage de ma fenêtre ensuite.

    Pour moi, le QMenu est le "conteneur" dans lequel on ajoute des "sousMenus" sur lesquels on peut agir.
    Il y a un mot clé par sousMenu c'est pour ça que je veux dériver un QAction.
    Comme exemple la barre de la fenêtre : Dans le menu Fichier on trouve les QAction "Nouvelle fenêtre", "Nouvel Onglet", "Ouvrir une fenêtre..." ...

    Enfin c'est possible que je l'utilise completement de travers aussi

  12. #12
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Ok, je comprend mieux.

    Le menu est bien le conteneur (un QMenu dans Qt) qui contient des items (des QAction dans Qt) et pas un sous-menu. Un sous menu, c'est un menu (donc un QMenu) contenu dans un menu (par exemple un liste de fichiers récents)
    C'est bien des QAction que tu veux utiliser.

    Donc, la question suivante était pourquoi créer une classe héritant de QAction ?
    A priori, tes QAction font juste leurs boulots : émettre un signal quand on clique dessus. Donc tu utilises le comportement par défaut des QAction et tu n'as pas besoin de créer une classe enfant.

    Normalement, tu dois simplement créer un slot par QAction et les connecter ensemble :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // lors de la création des menus
    QMenu * menu = new QMenu("Mon menu");
    QAction * etat1 = new QAction("Passer la fenêtre dans l'état 1", menu);
    menu->addAction(etat1);
    connect(etat1, SIGNAL(triggered()), this, SLOT(doEtat1()));
     
    // ton slot pour ton état 1
    void MainWindow::doEtat1()
    {
        // tu modifies l'affichage de ta fenêtre en donnant le mot clé correspondant
        modifierAffichageDeTaFenetre("mot clé état 1");
    }
    // idem pour chaque état possible
    Autre possibilité (si tu as beaucoup d'états possible ou si le nombre d'états est dynamique), tu récupères le triggered(QAction*) du QMenu :
    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
    // lors de la création des menus
    QMenu * menu = new QMenu("Mon menu");
    menu->addAction(new QAction("Passer la fenêtre dans l'état 1", menu));
    connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(doEtat(QAction*)));
     
    // ton slot pour tous tes états
    void MainWindow::doEtat(QAction * action)
    {
        // tu récupères le texte du QAction puis tu testes les différentes possibilités
        QString str = action->text();
        if(str == "Passer la fenêtre dans l'état 1")
            modifierAffichageDeTaFenetre("mot clé état 1");
        else
        if( ...
    }

  13. #13
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 63
    Points : 51
    Points
    51
    Par défaut
    Je vois ce que tu veux faire. Ca impliquerait que je connaisse toutes les possibilités de motCle et des menus.
    Seulement mon menu ainsi que les motCle sont totalement inconnus avant le lancement de l'appli.
    Je les charge depuis un fichier XML modifiable, c'est pour cette raison que je dérive un QAction, pour lui rajouter l'attribut motCle.
    Quand je parcours le XML, je créé tous mes objets QAction dérivés en leur ajoutant l'attribut motCle.

  14. #14
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    Autre possibilité (si tu as beaucoup d'états possible ou si le nombre d'états est dynamique),
    Ou tu utilise un QSignalMapper. C'est fait pour cela

    Après ça dépend du besoin. Le problème en récupérant le text de QAction est dans le cas de l'utilisation de traduction. Va savoir ce que sera le text.

  15. #15
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Ou tu utilise un QSignalMapper...
    J'ai pensé après que je n'avais pas signalé cette possibilité.

    Pour la traduction, tu as raison. Ça ne serait pas très "propre". Il faudrait dans cette solution utiliser les propriétés des QObject pour ajouter une propriété "keyword" par exemple.


    Avec QSignalMapper :

    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
    // lors de la création des menus
    QSignalMapper * mapper = new QSignalMapper(this);
    QMenu * menu = new QMenu("Mon menu");
    for ( /* pour chaque élément du xml */ )
    {
       QAction * action = new QAction(menu);
       action->setText( /* le QString du menu récupéré dans le xml */ );
       connect(action, SIGNAL(triggered()), mapper, SLOT(map()));
       mapper->setMapping(action, /* le mot clé récupéré du xml */ );
       menu->addAction(action);
    }
    connect(mapper, SIGNAL(mapped(const QString &)), this, SLOT(doEtat(const QString &)));
     
     
     
    // ton slot pour tous tes états
    void MainWindow::doEtat(const QString & str)
    {
        te->append( str );
    }


    Sans QSignalMapper :
    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
    // lors de la création des menus
    QMenu * menu = new QMenu("Mon menu");
    for ( /* pour chaque élément du xml */ )
    {
       QAction * action = new QAction(menu);
       action->setText( /* le QString du menu récupéré dans le xml */ );
       action->setProperty("keyword", QVariant( /* le mot clé récupéré du xml */ ));
       menu->addAction(action);
    }
    connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(doEtat(QAction*)));
     
     
     
    // ton slot pour tous tes états
    void MainWindow::doEtat(QAction * action)
    {
       // tu récupères le mot clé du QAction puis tu le transmets
       if(action->property("keyword").isValid())
          modifierAffichageDeTaFenetre( action->property("keyword").toString() );
    }

    Dans tous les cas, créer une classe héritant de QAction, même si c'est possible, n'est pas le plus simple dans ce cas (et appeler un item "sous menu" n'est pas vraiment judicieux)

    J'espère que ça t'aide un peu.

  16. #16
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    Pour la traduction, tu as raison. Ça ne serait pas très "propre". Il faudrait dans cette solution utiliser les propriétés des QObject pour ajouter une propriété "keyword" par exemple.

  17. #17
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 63
    Points : 51
    Points
    51
    Par défaut
    Merci beaucoup tout le monde, j'ai appris plein de choses.
    Vous êtes au top !

  18. #18
    Membre averti

    Homme Profil pro
    Inscrit en
    Février 2010
    Messages
    243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2010
    Messages : 243
    Points : 398
    Points
    398
    Par défaut
    J'ai déjà utilisé QActionGroup et
    void QAction::setData ( const QVariant & userData )
    pour setter le keyword

    ensuite un seul signal, QActionGroup.triggered() permet de récupérer le keyword de l'action cliquée...

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

Discussions similaires

  1. [POO] Héritage et redéfinition
    Par mamid1706 dans le forum C++
    Réponses: 6
    Dernier message: 07/05/2007, 17h25
  2. héritage et redéfinition de méthodes
    Par Braillane dans le forum Langage
    Réponses: 4
    Dernier message: 07/01/2007, 18h47
  3. Template, héritage multiple et redéfinition
    Par Paul Atreide dans le forum Langage
    Réponses: 5
    Dernier message: 31/10/2006, 14h00
  4. L'héritage multiple est-il possible en Delphi ?
    Par SchpatziBreizh dans le forum Langage
    Réponses: 8
    Dernier message: 30/06/2005, 11h30
  5. [Héritage] Redéfinition méthode
    Par petit-ourson dans le forum Langage
    Réponses: 9
    Dernier message: 06/05/2004, 16h06

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