Partage
  • Partager sur Facebook
  • Partager sur Twitter

Object::connect: No such slot QDialog::enregistrer

Qt : Création de slot personnalisé

Sujet résolu
    29 janvier 2015 à 10:27:32

    Bonjour,

     Je me suis lancé dans le TP ZeroClassGenerator du cours sur le langage C++. Je suis au niveau des "idées d'amélioration". Je suis en train d'essayer de sauvegarder les fichiers *.h et *.cpp dans des fichiers à partir de la boîte de dialogue qui affiche les codes source. J'ai commencé par essayer d'ajouter un bouton et essayer de le connecter avec un SLOT personnalisé hyper simple du style :

    void FenCodeGenere::enregistrerFichier()
    {
        QString fichier = QFileDialog::getSaveFileName(this, "Enregistrer un fichier", QString(), "Header C++ (*.h)");
    }

     Je l'appelle avec la fonction

    QObject::connect(m_boutonEnregistrer, SIGNAL(clicked()), this, SLOT(enregistrerFichier()));

     Lorsque je compile le programme tourne correctement jusqu'au moment où la première boîte de dialogue s'affiche. À ce moment là elle m'indique : Object::connect: No such slot QDialog::enregistrerFichier()

     Voici les codes complets de mon main et mes classes avec les headers maintenant.

     main.cpp

    #include "FenPrincipale.h"
    #include <QApplication>
    #include <QTextCodec>
    
    int main(int argc, char *argv[])
    {
        QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
        QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
    
        QApplication app(argc, argv);
        FenPrincipale fenetrePrincipale;
        fenetrePrincipale.show();
    
        return app.exec();
    }
    

    FenPrincipale.h

    #ifndef FENPRINCIPALE_H
    #define FENPRINCIPALE_H
    
    #include "FenCodeGenere.h"
    #include <QMainWindow>
    #include <QWidget>
    #include <QGroupBox>
    #include <QVBoxLayout>
    #include <QHBoxLayout>
    #include <QLineEdit>
    #include <QFormLayout>
    #include <QCheckBox>
    #include <QTextEdit>
    #include <QDateEdit>
    #include <QPushButton>
    #include <QMessageBox>
    
    /*namespace Ui {
    class FenPrincipale;
    }*/
    
    class FenPrincipale : public QWidget
    {
        Q_OBJECT
    
    public:
        FenPrincipale();
        ~FenPrincipale();
    
    private slots:
        void genererCode();
        void appliquerTexte(const QString& chaine);
    
    private:
        QLineEdit *m_nomClasse;
        QLineEdit *m_classeMere;
        QCheckBox *m_protections;
        QCheckBox *m_constructeur;
        QCheckBox *m_destructeur;
        QPushButton *m_generer;
        QPushButton *m_quitter;
        QPushButton *m_genererBis;
        QPushButton *m_quitterBis;
        QLineEdit *m_auteur;
        QDateEdit *m_dateCreation;
        QTextEdit *m_roleClasse;
        QGroupBox *m_groupCommentaires;
        QLineEdit *m_afficheProtections;
    };
    
    #endif // FENPRINCIPALE_H
    

    FenPrincipale.cpp

    #include "FenPrincipale.h"
    #include "ui_FenPrincipale.h"
    
    
    FenPrincipale::FenPrincipale() :
        QWidget()
    {
        //GROUPE DEFINITION
        //  Champs
        m_nomClasse = new QLineEdit;
        m_classeMere = new QLineEdit;
    
        QFormLayout *definitionLayout = new QFormLayout;
        definitionLayout->addRow("&Nom : ",m_nomClasse);
        definitionLayout->addRow("Classe &mere : ", m_classeMere);
    
        QGroupBox *groupDefinition = new QGroupBox("Définition de la classe");
        groupDefinition->setLayout(definitionLayout);
    
        //GROUPE OPTIONS
        m_protections = new QCheckBox("Protéger le &header contre les inclusions multiples");
        m_protections->setChecked(true);
    
        m_afficheProtections = new QLineEdit();
    
        connect(m_nomClasse,SIGNAL(textChanged(QString)),this,SLOT(appliquerTexte(QString)));
    
        m_constructeur = new QCheckBox("Générer un &constructeur par défaut");
        m_destructeur = new QCheckBox("Générer un &destructeur");
    
        QVBoxLayout *optionsLayout = new QVBoxLayout;
        optionsLayout->addWidget(m_protections);
        optionsLayout->addWidget(m_afficheProtections);
        optionsLayout->addWidget(m_constructeur);
        optionsLayout->addWidget(m_destructeur);
    
        QGroupBox *groupOptions = new QGroupBox("Options");
        groupOptions->setLayout(optionsLayout);
    
        //GROUPE COMMENTAIRES
        m_auteur = new QLineEdit("Juan");
        m_dateCreation = new QDateEdit;
        m_dateCreation->setDate(QDate::currentDate());
        m_roleClasse = new QTextEdit;
    
        QFormLayout *commentairesLayout = new QFormLayout;
        commentairesLayout->addRow("&Auteur", m_auteur);
        commentairesLayout->addRow("Da&te de création", m_dateCreation);
        commentairesLayout->addRow("&Rôle de la classe", m_roleClasse);
    
        m_groupCommentaires = new QGroupBox("Ajouter des commentaires");
        m_groupCommentaires->setCheckable(true);
        m_groupCommentaires->setChecked(true);
        m_groupCommentaires->setLayout(commentairesLayout);
    
        //BOUTONS GENERER ET QUITTER
        m_generer = new QPushButton("Générer");
        m_quitter = new QPushButton("Quitter");
    
        QHBoxLayout *boutonsLayout = new QHBoxLayout;
        boutonsLayout->addWidget(m_generer);
        boutonsLayout->addWidget(m_quitter);
        boutonsLayout->setAlignment(Qt::AlignRight);
    
    
        //LAYOUT PRINCIPAL
        QVBoxLayout *layoutPrincipal = new QVBoxLayout;
        layoutPrincipal->addWidget(groupDefinition);
        layoutPrincipal->addWidget(groupOptions);
        layoutPrincipal->addWidget(m_groupCommentaires);
        layoutPrincipal->addLayout(boutonsLayout);
        setLayout(layoutPrincipal);
        QObject::connect(m_quitter, SIGNAL(clicked()), qApp, SLOT(quit()));
        QObject::connect(m_generer, SIGNAL(clicked()), this, SLOT(genererCode()));
    
    
    
        setWindowTitle("Zero Class Generator");
        //setMinimumSize(384,563);
    }
    
    void FenPrincipale::appliquerTexte(const QString& chaine) //slot pour remplacer le SLOT(setText(QString)) dans le connect avec m_nomClasse
    {
        m_afficheProtections->setText("HEADER_" + chaine.toUpper() + "_H");
    }
    
    FenPrincipale::~FenPrincipale()
    {
        delete m_nomClasse;
        delete m_classeMere;
        delete m_generer;
        delete m_quitter;
    }
    
    void FenPrincipale::genererCode()
    {
        // On vérifie que le nom de la classe n'est pas vide, sinon on arrête
        if(m_nomClasse->text().isEmpty())
        {
            QMessageBox::critical(this, "Impossible de générer le code", "Veuillez renseigner au moins le nom de la classe");
        }
        else
        {
            // Si tout va bien on génére le code
            QString codeHeader;
            QString codeSource;
    
            // On ajoute les commentaires au code s'il y en a
            if(m_groupCommentaires->isChecked())
            {
                codeHeader += "/*\nAuteur : " + m_auteur->text() + "\n";
                codeHeader += "Date de création : " + m_dateCreation->date().toString() + "\n\n";
                codeHeader += "Rôle de la classe :\n" + m_roleClasse->toPlainText() + "\n*/ \n\n";
                codeSource += "#include " + m_nomClasse->text() + ".h\n\n";
            }
    
            // On ajoute les options choisies
            /*if(m_protections->isChecked())
            {
                codeHeader += "#ifndef HEADER_" + m_nomClasse->text().toUpper() + "_H\n";
                codeHeader += "#define HEADER_" + m_nomClasse->text().toUpper() + "_H\n\n";
            }*/
            if(m_protections->isChecked())
            {
                codeHeader += "#ifndef " + m_afficheProtections->text().toUpper() + "\n";
                codeHeader += "#define " + m_afficheProtections->text().toUpper() + "\n\n";
            }
    
            codeHeader += "class " + m_nomClasse->text();
    
            // ---si m_classeMere contient du texte, on l'ajoute
            if(!m_classeMere->text().isEmpty())
            {
                codeHeader += " : public " + m_classeMere->text();
            }
    
            // ---sinon on fait sans la classe mère
            codeHeader += "\n{\n    public:\n";
    
            // ---si la case constructeur est cochée, on le crée avec le nom de la classe
            if(m_constructeur->isChecked())
            {
                codeHeader += "        " + m_nomClasse->text() + "();\n";
                codeSource += m_nomClasse->text() + "::" + m_nomClasse->text() + "()";
                if (!m_classeMere->text().isEmpty())
                {
                    codeSource += " : " + m_classeMere->text() + "()";
                }
                codeSource += "\n{\n\n}";
            }
    
            // ---si la case destructeur est cochée, on le crée avec le nom de la classe
            if(m_destructeur->isChecked())
            {
                codeHeader += "        ~" + m_nomClasse->text() + "();\n";
                codeSource += "\n\n" + m_nomClasse->text() + "::~" + m_nomClasse->text() + "()";
                codeSource += "\n{\n\n}";
            }
    
            // on termine d'ajouter le texte minimal
            codeHeader += "\n    protected:\n\n    private:\n\n}";
    
            // on refait un test sur la case protections pour ajouter le text final
            if(m_protections->isChecked())
            {
                codeHeader += "\n#endif // " + m_nomClasse->text().toUpper() + "_H\n";
            }
    
            // On crée puis affiche la fenêtre qui affichera le code généré, qu'on lui envoie en paramètre
            FenCodeGenere *fenetreCode = new FenCodeGenere(codeHeader, codeSource, this);
            fenetreCode->exec();
        }
    }
    

    FenCodeGenere.h

    #ifndef FENCODEGENERE_H
    #define FENCODEGENERE_H
    
    #include "FenPrincipale.h"
    #include <QWidget>
    #include <QPushButton>
    #include <QTextEdit>
    #include <QDialog>
    #include <QFileDialog>
    #include <fstream>
    
    class FenCodeGenere : public QDialog
    {
    public:
        FenCodeGenere(QString &codeHeader, QString &codeSource, QWidget *parent);
    
    private slots:
        void enregistrerFichier();
    
    private:
        QPushButton *m_boutonFermer;
        QPushButton *m_boutonEnregistrer;
        QTextEdit *m_afficheCodeHeader;
        QTextEdit *m_afficheCodeSource;
    };
    
    #endif // FENCODEGENERE_H
    

    FenCodeGenere.cpp

    #include "FenCodeGenere.h"
    
    FenCodeGenere::FenCodeGenere(QString &codeHeader, QString &codeSource, QWidget *parent=0) : QDialog(parent)
    {
        //TABS
        QTabWidget *onglets = new QTabWidget(this);
        QWidget *page1 = new QWidget;
        QWidget *page2 = new QWidget;
    
        // Page 1
        m_afficheCodeHeader = new QTextEdit();
        m_afficheCodeHeader->setPlainText(codeHeader);
        m_afficheCodeHeader->setReadOnly(true);
        m_afficheCodeHeader->setFont(QFont("Courier"));
    
        // Layout Page 1
        QVBoxLayout *layoutHeader = new QVBoxLayout;
        layoutHeader->addWidget(m_afficheCodeHeader);
        page1->setLayout(layoutHeader);
    
        // Page 2
        m_afficheCodeSource = new QTextEdit();
        m_afficheCodeSource->setPlainText(codeSource);
        m_afficheCodeSource->setReadOnly(true);
        m_afficheCodeSource->setFont(QFont("Courier"));
    
        // Layout Page 2
        QVBoxLayout *layoutSource = new QVBoxLayout;
        layoutSource->addWidget(m_afficheCodeSource);
    
        page2->setLayout(layoutSource);
    
        // Ajout des onglets
        onglets->addTab(page1, "Header");
        onglets->addTab(page2, "Source");
    
        // BOUTONS
        m_boutonFermer = new QPushButton("Fermer");
        QObject::connect(m_boutonFermer, SIGNAL(clicked()), this, SLOT(accept()));
        m_boutonEnregistrer = new QPushButton("Enregistrer");
        QObject::connect(m_boutonEnregistrer, SIGNAL(clicked()), this, SLOT(enregistrerFichier()));
        QHBoxLayout *layoutBoutons = new QHBoxLayout;
        layoutBoutons->addWidget(m_boutonFermer);
        layoutBoutons->addWidget(m_boutonEnregistrer);
        layoutBoutons->setAlignment(Qt::AlignRight);
    
        // LAYOUT PRINCIPAL
        QVBoxLayout *layoutPrincipal = new QVBoxLayout;
        layoutPrincipal->addWidget(onglets);
        layoutPrincipal->addLayout(layoutBoutons);
        setLayout(layoutPrincipal);
        resize(350,450);
    }
    
    void FenCodeGenere::enregistrerFichier()
    {
        QString fichier = QFileDialog::getSaveFileName(this, "Enregistrer un fichier", QString(), "Header C++ (*.h)");
    }
    

    Le SLOT est définitivement là mais n'est pas reconnu par le compilateur. Je sais que quelque chose de très très simple et basique m'échappe mais je n'arrive pas à trouver quoi. Pouvez-vous m'éclairer?

    Merci par avance pour vos réponses.

    • Partager sur Facebook
    • Partager sur Twitter
      29 janvier 2015 à 10:31:03

      Tu as oublié la macro Q_OBJECT dans ta classe FenCodeGenere

      -
      Edité par Palador 29 janvier 2015 à 10:41:09

      • Partager sur Facebook
      • Partager sur Twitter
        29 janvier 2015 à 11:09:31

        AYA.... Je suis sans mots... Effectivement, c'était une faute gravement simple...

        Bon, en tout cas merci beaucoup @Palador! Ça fonctionne correctement maintenant!

        • Partager sur Facebook
        • Partager sur Twitter
          4 décembre 2019 à 7:12:31

          Q_OBJECT ne pas oublier de relancer la commande qmake après!
          • Partager sur Facebook
          • Partager sur Twitter

          Object::connect: No such slot QDialog::enregistrer

          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
          • Editeur
          • Markdown