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 :

Signals, slots et héritage


Sujet :

Qt

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Avatar de Niak74
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    271
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 271
    Par défaut Signals, slots et héritage
    Bonjour,
    je vais tenter de vous exposer brièvement mon problème.

    J'ai une classe mère (nommée ClasseMere) qui étend de QFrame, et une classe fille (nommée ClasseFille, qui étend donc de ClasseMere).

    Les classes filles sont construites selon les directives de la classe mère et possèdent des attributs qu'il est nécessaire de sauvegarder avant fermeture.
    Pour se faire, je comptais implémenter la modélisation suivante :

    La classe mère :
    - étend QFrame
    - possède un slot virtuel "void saveAndClose()"
    - redirige le signal d'un bouton fermer vers le slot virtuel "void saveAndClose()"

    La classe fille :
    - étend de la classe mère et propose ses propres attributs (à sauvegarder)
    - implémente le slot virtuel "void saveAndClose()" décrivant la manière de sauvegarder les données, et ferme la fenêtre.


    Voici à quoi ressemble ma classe mère (.h):

    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
     
    #include <QtGui>
     
    class ClasseMere : public QFrame
    {
    Q_OBJECT
     
    public:
    ClasseMere(QWidget *parent=0);
    virtual ~ClasseMere();
     
    void initialiseFenetre();
     
    public slot:
    virtual void saveAndClose() = 0;
     
    protected:
    virtual void initialiseContenuFenetre() = 0;
     
    //Contient les pointeurs vers les principaux éléments graphiques (Layouts, Widgets, Boutons, ect...)
    }
    et son .cpp :

    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
     
    ClasseMere::ClasseMere(QWidget *parent):QFrame(parent)
    {
    initialiseFenetre();
     
    //bouton close est un pointeur vers le bouton (QPushButton) permettant la fermeture de la fenêtre
    QObject::connect(bouton_close, SIGNAL(clicked()), this, SLOT(saveAndClose());
    }
     
    ClasseMere::~ClasseMere()
    {
    }
     
    ClaseeMere::initialiseFenetre()
    {
    //Création des éléments graphiques
     
    //...
    //...
    }
    Voici les fichiers de la classe fille : (.h)

    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
     
    class ClasseFille : public ClasseMere
    {
    Q_OBJECT
     
    ClasseFille(QWidget *parent = 0);
    virtual ~ClasseFille();
     
    public slot:
    void saveAndClose(); //Implémente de la classe mère
     
    protected:
    void initialiseContenuFenetre(); //Implémente de la classe mère
     
    //Contient les pointeurs vers les principaux éléments graphiques de la classe fille (Layouts, Widgets, Boutons, ect...)
    }
    Et son .cpp :

    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
     
    ClasseFille::ClasseFille(QWidget *parent):ClasseMere(parent)
    {
    initialiseContenuFenetre();
    }
     
    ClasseFille::~ClasseFille()
    {
    }
     
    ClasseFille::initialiseContenuFenetre()
    {
    //Construction des éléments graphique de la classe fille
     
    //...
    //...
    }
     
    ClasseFille::saveAndClose()
    {
    //Sauvegarde des infos
     
    //...
    //...
     
    this->close();
    }
    La compilation se déroule bien, l'erreur arrive à l'exécution :

    Object::connect: No such slot QFrame::saveAndClose()

    2 soucis :

    1) Je ne comprends pas pourquoi on cherche le slot saveAndClose() dans la classe QFrame alors que l'élément présent dans mon connect est bien une instance de la ClasseMere.

    Rappel :
    QObject::connect(bouton_close, SIGNAL(clicked()), this, SLOT(saveAndClose());

    2) Peut-être existe-t-il un autre moyen d'arriver à la fin souhaitée (appeler une méthode perso lors de la fermeture de la fenêtre, j'ai tenté d'exploité le signal "destroyed" de QFrame, mais celui-ci survient après la destruction, donc le contenu à exploité est perdu.


    Cette méthode me parait la plus propre pour créer plusieurs Classe filles différentes proposant chacune leurs propres éléments. Ici, il ne suffit que d'implémenter la construction de la fenêtre et la façon de sauvegarder les éléments dans la classe fille.

  2. #2
    Membre expérimenté
    Avatar de Niak74
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    271
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 271
    Par défaut
    En testant divers choses, je me suis rendu compte que le connect marche si il est écrit dans la classe fille.

    Le problème viendrait peut être du fait que le slot est virtuel pur, Qt cherche peut être alors ce slot dans la/les classes au dessus de ma classe mère...

    Ceci ne répond pas tout à fait à mon problème étant donné que je souhaite factoriser un maximum d'éléments dans ma classe mère, cette connexion comprise...

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 223
    Par défaut
    Bonjour.

    Je dit peut être une bêtise, mais ton sujet m'intéresse beaucoup
    Dans ton code, tu écris :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    QObject::connect(bouton_close, SIGNAL(clicked()), this, SLOT(saveAndClose());
    Tu indiques l'objet courant "this", donc la classe mère. Or, comme tu l'indiques, ton slot se traite dans ta classe fille. A tu essayer de pointer non pas sur ta classe mère, mais sur ta classe fille avec le connect ? parce que le fait que ta méthode soit virtuel ne suffit peut être pas
    Cordialement,
    PKO

  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
    Salut,
    Créé plutôt une fonction virtuel appelé par le slot. Un truc comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    private
    virtual void internalSaveAndClose() = 0;
     
    public slot:
    void saveAndClose()
    {
         internalSaveAndClose()
    }
    ou un fonction init qui fini l'initialisation : A appeler hors du constructeur


    si je me trompe pas ton constructeur ne peut marcher car la class fille n'est pas encore créé lors du connect et this est donc encore une ClasseMere :
    ClasseMere::ClasseMere(QWidget *parent):QFrame(parent)
    {
    initialiseFenetre();

    //bouton close est un pointeur vers le bouton (QPushButton) permettant la fermeture de la fenêtre
    QObject::connect(bouton_close, SIGNAL(clicked()), this, SLOT(saveAndClose());
    }
    EN gros ce qui se passe quand tu créé une class fille :
    1- la partie class QFrame est créé
    2- la partie class mère est créé et tu essaie de faire un connect
    3- la partie class fille est créé.

    Le connect est appliqué sur la class mère et non la class fille car sa partie n'est pas encore créé. Et comme la class mère n'as pas de slot saveAndClose() il essaie d'utiliser celle de QFrame qui n'existe pas

  5. #5
    Membre expérimenté
    Avatar de Niak74
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    271
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 271
    Par défaut
    J'ai modifié un peu le code de la classe mère :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    protected:
    virtual void saveAndClose() = 0;
     
    public slot:
    void saveAndCloseSlot()
    {
         saveAndClose();
    }
    Avec création des connections dans le constructeur : même erreur (impossible de trouver le slot QFrame::saveAndCloseSlot()).

    En déportant la création des connexion dans une méthode qui est ensuite appelée dans le main() : erreur : impossible de trouver le slot ClasseFille::saveAndCloseSlot().

    Je vais tester un petit truc...

  6. #6
    Membre expérimenté
    Avatar de Niak74
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    271
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 271
    Par défaut
    J'ai une réponse partielle au problème :

    Classe mère :

    - Créer le slot public virtuel pur saveAndClose()
    - Créer la méthode public makeConnections(), dans le cpp, établir les liens avec le slot saveAndClose()

    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
     
    ///////////////////////
         Header
    ///////////////////////
     
    public slot :
    virtual void saveAndClose() = 0;
     
    public: 
    void makeConnections()
     
    ///////////////////////
         Cpp
    ///////////////////////
     
    ClasseMere::makeConnections()
    {
    QObject::connect(bouton_fermer, SIGNAL(clicked()), this, SLOT(saveAndClose());
    }
    Classe fille :

    - implémenter le slot saveAndClose()

    Dans le main :

    - créer une instance de ClasseFille
    - appeler la méthode makeConnections de cette instance


    Cette méthode fonctionne. Cependant, elle me semble partielle car une ligne est à ajouter dans le main pour établir les connexions. Je m'en contenterai si il est impossible de faire mieux.

    Merci à vous pour les idées proposées =)

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    67
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 67
    Par défaut MOC
    je suis étonné de ne pas avoir entendu parler de moccing dans cette histoire...
    Pour que tout ca marche, ne faut-il pas que moc soit appelé sur les classes mères et filles????

    Je suis pas un spécialiste, hein. C'est plus une question qu'une piste...

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

Discussions similaires

  1. Signals/Slots et héritage
    Par agh dans le forum Débuter
    Réponses: 1
    Dernier message: 18/04/2010, 16h36
  2. Problème de connect (signal/slots)
    Par Alain Defrance dans le forum Qt
    Réponses: 5
    Dernier message: 20/03/2008, 21h58
  3. help signal slot
    Par psyko72 dans le forum Qt
    Réponses: 1
    Dernier message: 31/12/2007, 13h51
  4. Signals slots boost/libsigc++/Qt
    Par epsilon68 dans le forum Qt
    Réponses: 14
    Dernier message: 10/08/2006, 21h31
  5. Connexion "directe" signal - slot
    Par broidsy dans le forum Qt
    Réponses: 3
    Dernier message: 27/02/2006, 09h37

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