Partage
  • Partager sur Facebook
  • Partager sur Twitter

Qt QString et boîte de dialogue

Problème avec l'affichage d'une boite de dialogue

Sujet résolu
Anonyme
    19 janvier 2019 à 20:50:46

    Bonjour,

    Je ne suis pas un expert de Qt, mais j'essaie de créer un programme (très simple) visant à récolter des informations entrées par l'utilisateur dans un QLineEdit, pour ensuite lui souhaiter la bienvenue dans une boite de dialogue.

    Le code s’exécute sans problème, cependant la boite de dialogue n'affiche ni le prénom ni le nom entrés par l'utilisateur, et je ne comprends pas bien pourquoi. Elle affiche juste "Bienvenue, !".

    Voici mon code :

    main.cpp

    #include "fenetre.h"
    
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        MaFenetre fenetre;
    
        fenetre.show();
    
        return app.exec();
    }
    

    fenetre.h

    #ifndef FENETRE_H
    #define FENETRE_H
    
    #include <QApplication>
    #include <QObject>
    #include <QLineEdit>
    #include <QPushButton>
    #include <QVBoxLayout>
    #include <QHBoxLayout>
    #include <QFormLayout>
    #include <QMessageBox>
    #include <QString>
    
    class MaFenetre : public QWidget
    {
        Q_OBJECT
    
        public :
           MaFenetre();
    
        public slots :
           void boiteDialogue();
    
        private :
           QPushButton *m_boutonOk;
           QPushButton *m_boutonQuitter;
           QString *m_message;
    };
    
    #endif // FENETRE_H

    fenetre.cpp

    #include "fenetre.h"
    
    MaFenetre::MaFenetre() : QWidget()
    {
        QLineEdit *nom = new QLineEdit;
        QLineEdit *prenom = new QLineEdit;
        QLineEdit *age = new QLineEdit;
    
        QFormLayout *layoutFormulaire = new QFormLayout;
        layoutFormulaire->addRow("Votre &nom :", nom);
        layoutFormulaire->addRow("Votre &prénom :", prenom);
        layoutFormulaire->addRow("Votre &age :", age);
    
    
        QVBoxLayout *layoutPrincipal = new QVBoxLayout;
        layoutPrincipal->addLayout(layoutFormulaire); 
    
        m_boutonQuitter = new QPushButton("Quitter");
        m_boutonOk = new QPushButton("OK");
    
        QHBoxLayout *layoutBoutons = new QHBoxLayout;
        layoutBoutons->addWidget(m_boutonOk);
        layoutBoutons->addWidget(m_boutonQuitter);
    
        layoutPrincipal->addLayout(layoutBoutons);
    
        QWidget::connect(m_boutonQuitter, SIGNAL(clicked()), qApp, SLOT(quit()));
        QWidget::connect(m_boutonOk, SIGNAL(clicked()), this, SLOT(boiteDialogue()));
    
        m_message = new QString("Bienvenue, " + prenom->text() + " " + nom->text() + " !");
    
        setLayout(layoutPrincipal);
    }
    
    void MaFenetre::boiteDialogue()
    {
        QMessageBox::information(this, QString("Welcome"), QString(*m_message));
    }
    

    Voilà, merci d'avance !



    • Partager sur Facebook
    • Partager sur Twitter
      19 janvier 2019 à 21:36:44

      Salut 

      pourquoi declare-tu ton m_message(QString) comme étant un pointeur ?

      ton problème est qu’au Lieu de passer une chaîne de caractères comme message à afficher toi tu lui passe un pointeur 

      • Partager sur Facebook
      • Partager sur Twitter

      Ton présent détermine ton futur et la connaissance te placera au dessus de ta génération .

      Anonyme
        19 janvier 2019 à 23:00:35

        Salut,

        Je mets QString(*m_message) comme argument de ma fonction QMessageBox::information, cela ne devrait donc pas poser de problème, si ?

        En tous cas, j'ai essayé en remplaçant le pointeur par une variable QString normale comme tu me l'as dit, et ça n'affiche toujours pas le bon message...

        • Partager sur Facebook
        • Partager sur Twitter
          20 janvier 2019 à 1:41:04

          Il n'y a effectivement pas besoin d'utiliser des pointeurs pour QString. De manière générale, il n'y a pas besoin de pointeur pour les conteneurs de Qt. Tu n'as pas non plus besoin de remettre QString(...), l'expression est déjà QString, c'est une information redondante.

          Et sinon, à quoi te sert m_message ? Quelle valeur contient la variable avant d'afficher la boîte de dialogue ? Quand change la valeur ?

          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            20 janvier 2019 à 11:28:28

            Je sais que le fait de remarquer QString(...) crée une redondance, mais en voyant que ça ne marchait pas sans, j'ai commencé à modifier mon code de façon subtile pour voir si des changements comme celui là pouvait faire fonctionner le programme...

            En fait, j'ai créer une variable m_message juste pour voir si cela marcherait mieux. A le base, j'ai écrit :

            QMessageBox::information(this, "Welcome", "Bienvenue, " + prenom->text() + " " + nom->text() + " !")

            Et cela ne m'affichait ni le nom ni le prénom, donc je me suis dit "essayons d'entrer une seule variable comme troisième argument de QMessageBox::information et voir si ça marche". Mais non.

            Et je déclare juste m_message juste dans mon .h. Ensuite je lui affecte la valeur :

            m_message = "Bienvenue, " + prenom->text() + " " + nom->text() + " !";

            (Ce n'est plus un pointeur car j'ai modifié la variable, comme je l'ai dit dans mon message au dessus).

            • Partager sur Facebook
            • Partager sur Twitter
              20 janvier 2019 à 17:16:13

              > A le base, j'ai écrit :

              QMessageBox::information(this, "Welcome", "Bienvenue, " + prenom->text() + " " + nom->text() + " !")

              C'est pourtant la bonne manière de faire. Mais pour cela, il faut que prenom et nom soient des membres de la classe.

              Au passage, les connect avec SLOT et SIGNAL sont désuets au profil de simple pointeur de fonction.

                  QWidget::connect(m_boutonQuitter, &QPushButton::clicked, qApp, &QApplication::quit);
                   // avec une lambda, pas besoin de MaFenetre::boiteDialogue
                  QWidget::connect(m_boutonOk, &QPushButton::clicked, this, [=]{
                    QMessageBox::information(this, QString("Welcome"), "Bienvenue, " + prenom->text() + " " + nom->text() + " !");
                  });
              

              Aussi, ton .h contient beaucoup trop d'includes inutiles.

              • Partager sur Facebook
              • Partager sur Twitter
              Anonyme
                20 janvier 2019 à 19:42:00

                >  Mais pour cela, il faut que prenom et nom soient des membres de la classe.

                Je pense que tout le problème venait de là. Une fois que je les déclare comme membre de ma classe, ça marche. Merci à toi !

                Je vais me renseigner sur les lambda, je ne connaissais pas.

                > Aussi, ton .h contient beaucoup trop d'includes inutiles. 

                Lesquels ?





                -
                Edité par Anonyme 20 janvier 2019 à 19:44:01

                • Partager sur Facebook
                • Partager sur Twitter
                  20 janvier 2019 à 20:04:50

                  Salut,

                  On va faire simple : à part QWidget, qui représente l'élément de base de ta classe et QString qui est utilisé sous forme de valeur, tous...

                  En effet, lorsque tu déclares des pointeurs vers des éléments, le compilateur peut se contenter de savoir que les éléments en question existent dans le fichier d'en-tête, et une déclaration anticipée suffit.

                  Il faut, par contre, inclure le fichier d'en-tête qui définit l'élément pointé dans le fichier d'implémentation (*.cpp)

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                  Anonyme
                    20 janvier 2019 à 21:17:25

                    Je ne suis pas sûr de bien comprendre...

                    Si j'enlève les #include, le programme ne marchera plus. Je ne comprends pas bien ce que tu me propose de faire à la place... De mettre mes #include dans le .cpp ? 

                    • Partager sur Facebook
                    • Partager sur Twitter
                      20 janvier 2019 à 21:44:54

                      Oui,

                      un fichier doit inclure ce dont lui même à besoin rien de plus. A chacun d'inclure ce qui lui manque, et ne jamais trop en vouloir. Surtout dans les fichiers d'entête, trop d'inclusion peuvent amener des problèmes complexes de cycles d'inclusion.

                      • Partager sur Facebook
                      • Partager sur Twitter

                      En recherche d'emploi.

                      Anonyme
                        20 janvier 2019 à 22:02:19

                        Ah bon, je n'aurais pas pensé que ça faisait une réelle différence o_O

                        Merci à tous ceux qui m'ont répondu en tout cas !

                        • Partager sur Facebook
                        • Partager sur Twitter
                          21 janvier 2019 à 15:50:16

                          Il faut comprendre que la seule chose dont on soit sur à propos d'un fichier d'en-tête, c'est qu'il a de très fortes chances de se retrouver inclus dans un un autre fichier.

                          Le problème, c'est que le mécanisme d'inclusion consiste, "tout simplement", à remplacer la commande #inclulde <fichier> par  le contenu du fichier en question, et ce, de manière récursive : si A inclut B, que B inclut C et que C inclus D, le préprocesseur va copier le contenu de B dans A, puis il va croiser (dans le contenu de B) l'inclusion de C, dont il va donc copier le contenu à l'endroit où se trouve l'instruction, et qu'il va enfin croiser l'inclusion de D (dans ce qui est le contenu de C), et qu'il va donc copier le contenu de D dans A

                          La seule inclusion du fichier d'en-tête <iostream>, par exemple -- pour profiter de std::cin et de std::cout-- va ajouter plus de 28 000 lignes de code dans ton fichier.

                          Mais ce sont donc plus de 28 000 lignes de code que le compilateur devra traiter pour générer le code binaire exécutable.  Et la compilation est un processus dont le temps pour l'exécuter augmente de manière significative par rapport au nombre d'instructions :p : il mettra sans doute deux fois plus longtemps à compiler 28 000 lignes de code qu'à en compiler... 14 000 .

                          Plus tu rajouteras d'inclusions dans un de tes fichiers d'en-tête, plus tu augmenteras donc -- d'office -- le temps nécessaire à la compilation de tous les fichiers d'implémentations qui ont besoin de ton fichier d'en-tête.

                          C'est la raison pour laquelle on essaye de limiter les inclusions au stricte minimum dans le fichier d'en-tête, en laissant le soin à celui qui écrit le fichier d'implémentation d'ajouter les en-tête dont il a réellement besoin.

                          Ainsi, pour reprendre ton exemple d'origine, en le corrigeant un tout petit peu, on va préférer travailler sous une forme proche de

                          #ifndef FENETRE_H
                          #define FENETRE_H
                          /* j'ai besoin de QWidget, qui  est la classe de base de MaFenetre
                           */
                          #include <QWidget>
                          /* j'ai besoin de QString, à cause de la donnée membre m_message
                           */
                          #include <QString>
                          /* Je dois faire comprendre au compilateur que la classe
                           * QushButton existe.  C'est tout ce dont il a besoin pour
                           * l'instant
                           */
                          class QPushButton;
                          
                          class MaFenetre : public QWidget
                          {
                              Q_OBJECT
                           
                              public :
                                 MaFenetre();
                           
                              public slots :
                                 void boiteDialogue();
                           
                              private :
                                 QPushButton *m_boutonOk;
                                 QPushButton *m_boutonQuitter;
                                 QString m_message;
                          };
                           
                          #endif // FENETRE_H

                          Ensuite, dans le fichier d'implémentation, je pourrai inclure les fichiers d'en-tête dont j'ai vraiment besoin, par exemple

                          #include "fenetre.h"
                          /* je les mets dans l'ordre dans lequel j'en aurai besoin ...
                           * je commence par les données membre de la classe (les
                           * QPushButton), puis je rajoute ceux dont j'ai besoin 
                           * dans l'ordre dans lequel ils apparaissent dans le 
                           * constructeur... D'autres solutions sont possibles
                           * (certains aiment avoir les fichiers d'en-tête triés par
                           * ordre alphabétique, par exemple)
                           */
                          #include <QPushButton>
                          #include <QLineEdit>
                          #include <QFormLayout>
                          #include <QVBoxLayout>
                          #inclde  <QHBoxLayout>
                          MaFenetre::MaFenetre(){
                              QLineEdit * nom = new QLineEdit;
                              QLineEdit * prenom = new QLineEdit;
                              QLineEdit * age = new QLineEdit;
                          
                              QFormLayout * layoutFormulaire = QFormLayout;
                              layoutFormulaire->addRow("Votre &nom :", nom);
                              layoutFormulaire->addRow("Votre &prénom :", prenom);
                              layoutFormulaire->addRow("Votre &age :", age);
                          
                              m_boutonQuitter  = new QPushButton("Quitter");
                              m_boutonOk       = neq QPushButton("Ok");
                              QVBoxLayout * layoutPrincipal = new QVBoxLayout;
                          
                              layoutPrincipal->addLayout(layoutFormulaire);
                              
                              QHBoxLayout * layoutBoutons = new QHBoxLayout;
                              layoutBoutons->addWidget(m_boutonOk);
                              layoutBoutons->addWidget(m_boutonQuitter);
                              /* ... */
                          }

                          De cette manière, tu es sur que le fichier d'en-tête (fenetre.h) ne fourni que "le stricte nécessaire" pour pouvoir créer la fenêtre ;)

                          -
                          Edité par koala01 21 janvier 2019 à 15:50:41

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                          Anonyme
                            22 janvier 2019 à 20:51:08

                            On ne peut pas être plus clair ! :lol:

                            Merci pour toutes ces informations !

                            • Partager sur Facebook
                            • Partager sur Twitter

                            Qt QString et boîte de dialogue

                            × 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