Partage
  • Partager sur Facebook
  • Partager sur Twitter

Qt un problème d'affichage

Sujet résolu
    21 août 2019 à 20:12:45

    Salut,

    Je suis en train de suivre le tuto sur Qt et je pense ne pas avoir compris un petit detail qui me fait bien .....

    Alors c'est le zeroClassGenerator

    Je m'occupe de la vision layout et companie voici le code du main

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

    Ensuite il le header

    #ifndef FENETREPRINCIPAL_H
    #define FENETREPRINCIPAL_H
    
    #include <QWidget>
    #include <QApplication>
    #include <QLineEdit>
    #include <QFormLayout>
    #include <QCheckBox>
    #include <QDialog>
    
    #include <QLabel>
    #include <QTextEdit>
    #include <QPushButton>
    #include <QGroupBox>
    #include <QDateEdit>
    
    class FenetrePrincipal : public QWidget
    {
        Q_OBJECT
    public:
        FenetrePrincipal();
    
    private :
        QLineEdit *nom;
        QLineEdit *classeMere;
        QCheckBox *protections;
        QCheckBox *genererConstructeur;
        QCheckBox *genererDestructeur;
        QGroupBox *groupCommentaires;
        QLineEdit *auteur;
        QDateEdit *date;
        QTextEdit *role;
        QPushButton *generer;
        QPushButton *quitter;
    
    };
    
    #endif // FENETREPRINCIPAL_H
    

    Et le constructeur de la classe

    #include "fenetreprincipal.h"
    
    FenetrePrincipal::FenetrePrincipal()
    {
    
    
        QVBoxLayout *verticallayout = new QVBoxLayout;
        QHBoxLayout *horizontallayout = new QHBoxLayout;
        QWidget fenetre;
    
    
        QLineEdit *nom = new QLineEdit;
        QLineEdit *classeMere = new QLineEdit;
    
        QCheckBox *inclusionMultiple = new QCheckBox;
        QCheckBox *constructeur = new QCheckBox;
        QCheckBox *destructeur = new QCheckBox;
    
        QCheckBox *commentaire = new QCheckBox;
        QLineEdit *autheur = new QLineEdit;
        QDateEdit *calendrier = new QDateEdit;
        
    
    
        QFormLayout *formulaire1Layout = new QFormLayout;
        QFormLayout *formulaire2Layout = new QFormLayout;
        QFormLayout *formulaire3Layout = new QFormLayout;
        QTextEdit *commentaireEcris = new QTextEdit;
    
        QPushButton *generate= new QPushButton("Générer");
        QPushButton *quit = new QPushButton("Quit");
    
        formulaire1Layout->addRow("Nom de la classe", nom);
        formulaire1Layout->addRow("Nom de la classe mère", classeMere);
    
        formulaire2Layout->addRow("Générer header avec protection contre inclusion multiple",inclusionMultiple);
        formulaire2Layout->addRow("Générer constructeur",constructeur);
        formulaire2Layout->addRow("Générer destructeur",destructeur);
    
        formulaire3Layout->addRow("Générer destructeur",commentaire);
        formulaire3Layout->addRow("Nom autheur",autheur);
        formulaire3Layout->addRow("calendrier",calendrier);
        formulaire3Layout->addRow("Rôle de la classe",commentaireEcris);
    
    
    
        horizontallayout->addWidget(generate);
        horizontallayout->addWidget(quit);
    
        verticallayout->addLayout(formulaire1Layout);
        verticallayout->addLayout(formulaire2Layout);
        verticallayout->addLayout(formulaire3Layout);
        verticallayout->addLayout(horizontallayout);
    
        fenetre.setLayout(verticallayout);
    
    }
    

    Quand je mets le code du constructeur dans le main cela fonctionne, par contre cela ne fonctionne plus une fois que je construit un objet avec. Pourtant ici quand je fais fenetre.show(); ça fonctionnne pas quelqu'un aurait une idée? :)



    • Partager sur Facebook
    • Partager sur Twitter
      21 août 2019 à 21:15:50

      Salut,

      Retire tous les types des widgets que  tu crées dans le constructeur :

      FenetrePrincipal::FenetrePrincipal()
      {
       
       
          QVBoxLayout *verticallayout = new QVBoxLayout;
          QHBoxLayout *horizontallayout = new QHBoxLayout;
          QWidget fenetre;
       
       
          nom = new QLineEdit;
          classeMere = new QLineEdit;
       
          inclusionMultiple = new QCheckBox;
          constructeur = new QCheckBox;
          destructeur = new QCheckBox;
       
          commentaire = new QCheckBox;
          autheur = new QLineEdit;
          calendrier = new QDateEdit;
          /*...*/

      Car le problème vient du fait que tu déclares des membre pour ta classe (dans le fichier d'en-tête).  Tu dois donc veiller à leur assigner l'adresse mémoire qui y correspond dans le constructeur.

      Sauf que, avec un code proche de QLineEdit *nom = new QLineEdit; dans le constructeur, tu déclares une variable locale à la fonction qui va ... cacher au compilateur l'existence de la donnée membre.

      Au final, la donnée membre (celle qui sera utilisée dans toutes les autres fonctions que le constructeur, gardera, au mieux, une valeur équivalente à nullptr (un pointeur inexistant), au pire, une valeur correspondant aux crasses laissées par une utilisation antérieure de la mémoire.  Mais, en aucun cas, à l'adresse mémoire à laquelle se trouve effectivement le widget concerné.

      • 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
        21 août 2019 à 22:02:38

        Salut merci de ta réponse

        Mais j'ai l'impression que ce n'est pas assez j'ai toujours une fenêtre vide

        J'ai peut être oublier des détail encore. 

        Revoici mon header et mon constructeur

        #include "fenetreprincipal.h"
        
         FenetrePrincipale:: FenetrePrincipale()
        {
        
        
            QVBoxLayout *verticallayout = new QVBoxLayout;
            QHBoxLayout *horizontallayout = new QHBoxLayout;
            QWidget fenetre;
        
        
        
            nom = new QLineEdit;
            classeMere = new QLineEdit;
        
            protections = new QCheckBox;
            genererConstructeur = new QCheckBox;
            genererDestructeur = new QCheckBox;
        
            commentaire = new QCheckBox;
            auteur = new QLineEdit;
            date = new QDateEdit;
            role = new QTextEdit;
        
        
            QFormLayout *formulaire1Layout = new QFormLayout;
            QFormLayout *formulaire2Layout = new QFormLayout;
            QFormLayout *formulaire3Layout = new QFormLayout;
        
        
            generer= new QPushButton("Générer");
            quitter = new QPushButton("Quit");
        
            formulaire1Layout->addRow("Nom de la classe", nom);
            formulaire1Layout->addRow("Nom de la classe mère", classeMere);
        
            formulaire2Layout->addRow("Générer header avec protection contre inclusion multiple",protections);
            formulaire2Layout->addRow("Générer constructeur",genererConstructeur);
            formulaire2Layout->addRow("Générer destructeur",genererDestructeur);
        
            formulaire3Layout->addRow("Générer destructeur",commentaire);
            formulaire3Layout->addRow("Nom autheur",auteur);
            formulaire3Layout->addRow("calendrier",date);
            formulaire3Layout->addRow("Rôle de la classe",role);
        
        
        
            horizontallayout->addWidget(generer);
            horizontallayout->addWidget(quitter);
        
            verticallayout->addLayout(formulaire1Layout);
            verticallayout->addLayout(formulaire2Layout);
            verticallayout->addLayout(formulaire3Layout);
            verticallayout->addLayout(horizontallayout);
        
            fenetre.setLayout(verticallayout);
        
        
        }
        
        #ifndef FENETREPRINCIPAL_H
        #define FENETREPRINCIPAL_H
        
        #include <QtWidgets>
        #include <QtGui>
        
        class FenetrePrincipale : public QWidget
        {
            Q_OBJECT
        
            public:
            FenetrePrincipale();
        
        
            private:
            QLineEdit *nom;
            QLineEdit *classeMere;
            QCheckBox *protections;
            QCheckBox *genererConstructeur;
            QCheckBox *genererDestructeur;
            QCheckBox *commentaire;
            QLineEdit *auteur;
            QDateEdit *date;
            QTextEdit *role;
            QPushButton *generer;
            QPushButton *quitter;
        
        };
        
        #endif // FENETREPRINCIPAL_H
        

        Et sérieusement je trouve que le c++ pour l'apprendre, bah faut s'accrocher !!!



        • Partager sur Facebook
        • Partager sur Twitter
          22 août 2019 à 11:02:39

          Peux tu me dire à quoi sert ton widget "fenetre" dans ton constructeur? n'es tu pas -- justement -- occupé à créer une classe qui est sensée, si on en croit le nom, servir de ... fenêtre principale ?

          Ne serait-il donc pas "logique" que le VBoxLayout (qui contient tous les HBoxLayout, qui contiennent ensemble tous les widgets que tu veux afficher) serve pour ... la classe FenetrePrincipale ?

          Or, dans ton code, tu crées tes widgets, que tu distribue (très logiquement) entre trois layout horzontaux, que tu va (tout aussi logiquement) placer dans un layout vertical.  Mais, ce layout vertical, tu le donne à ... un widget nommé fenetre.

          Ce n'est pas mal en soi, si ce n'est que ce widget est créé... sur la pile (sans avoir recours à l'allocation dynamique de la mémoire), au lieu d'être créé sur le tas (en appelant new pour le créer).  Cela implique que ce widget sera détruit automatiquement lorsqu'on atteindra l'accolade fermante du constructeur.

          Du coup, le système parent/enfants de Qt va provoquer

          • la destruction du layout vertical, dont le widget fenetre est le parent direct, ce qui provoquera
          • la destruction des layout horizontaux, dont le layout vertical est le parent direct (et dont le widget fenêtre est le "grand parent"), ce qui provoquera
          • la destruction de tous les widgets que tu a eu tant de mal à créer (dont les layouts horizontaux sont les parent, le layout vertical le "grand parent" et dont le widget fenêtre est "l'ancêtre"

          Tu vois un peu où est le problème?  Mais du coup, peut-être vois tu la solution ?

          Je vais te laisser réfléchir à cette solution, car je crois t'avoir donné toutes les informations utiles à la résolution du problème. 

          Je vais juste te dire qu'il y a deux solutions possibles en l'état, et que je me contenterai d'une seule, même si, à mon gout, il y en a une qui me semble préférable à l'autre ;)

          • 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
            22 août 2019 à 11:34:27

            J'ai réussi avec une solutions plus logique

            this->setLayout(verticallayout)

            Au lieu de fenêtre, par contre si je déclare le widget fenetre sur le tas avec un new ça marche pas non plus. Peux-tu m'éclaircir sur la deuxième méthode que je ne vois pas?

            • Partager sur Facebook
            • Partager sur Twitter
              22 août 2019 à 13:35:09

              Don_raftapss a écrit:

              J'ai réussi avec une solutions plus logique

              this->setLayout(verticallayout)

              C'était bien celle que j'espérais te voir utiliser :D

              Don_raftapss a écrit:

              Au lieu de fenêtre, par contre si je déclare le widget fenetre sur le tas avec un new ça marche pas non plus. Peux-tu m'éclaircir sur la deuxième méthode que je ne vois pas?

              En déclarant le widget fenetre sur le tas (donc, effectivement, en le créant sous la forme de QWidget * fenetre = new QWidget;), et en plaçant le layout horzontal dans ce widget (à l'aide de fenetre->setLayout(verticallayout);, tu aurais pu définir ce widget particulier comme étant le "widget central" de ta fenêtre principale avec le code setCentralWidget(fenetre);

              Mais, pour être complet, l'idéal aurait alors été de créer une deuxième classe, héritée de QWidget, et regroupant tout les widgets (et les layouts) que tu a définis dans le constructeur de FenetrePrincipale, afin de pouvoir le créer "en une seule fois" sous une forme proche de
              /* on considère que tout le contenu appartient au 
               * widget personnalisé nommé "MyWidget", déclaré
               * dans le fichier d'en-tête MyWidget.hpp
               */
              #include <MyWidget.hpp>
              FenetrePrincipale::FenetrePrincipale(){
                  MyWidget * widgetCentral;
                  setCentralWidget(widgetCentral);
              }

              -
              Edité par koala01 22 août 2019 à 13:35:31

              • 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
                22 août 2019 à 16:54:20

                Et ben merci pour toute tes explications :) Le sujet est donc résolu et j'ai appris je suis content :)

                Bien à toi 

                • Partager sur Facebook
                • Partager sur Twitter

                Qt un problème d'affichage

                × 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