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

Discussion :

Construire une boîte de dialogue proprement

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut Construire une boîte de dialogue proprement
    Bonsoir,

    J'ai construit un QDialog comprenant une QLineEdit mais je ne suis pas sûr j'ai l'impression d'y être allé comme un bourrin.

    Alors voilà : dans l'entête j'ai déclaré dans la classe MainWindow :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    QLineEdit l;
    QDialog d;
    Dans le constructeur de MainWindow :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    l.setParent(&d) // ça n'est pas un "un" mais un "elle" (l quoi)
    Et le dialogue apparaît/disparaît plus tard soit avec show()/close() ou exec() mais on s'en fiche.

    Je ne sais pas : il y a un truc qui me chiffonne quand même...

    Pensez-vous que je dois consulter ?

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    En effet, tu y es allé "comme un bourrin"

    Et tu prend de très gros risques (d'erreur de segmentation ) qui plus est.

    Si tu veux créer une boite de dialogue personnalisée, tu dois créer une classe qui représentera cette boite de dialogue et qui hérite de QDialog.

    En gros, tu dois avoir une classe qui ressemblera à quelque chose comme
    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
    class MyDialog : public QDialog{
        Q_OBJECT
        public:
            MyDialog(QWidget * parent /* = 0 */);
            /* peut etre beaucoup de choses ici ;) */
        private:
            QLineEdit * edit; // pour pouvoir le récupérer "facilement" ;)     
            /* peut être d'autres parties auxquelles tu voudras pouvoir accéder ici */
    };
     
    MyDialog::MyDialog(QWidget * parent):QDialog(parent){
        edit  = new QLineEdit;
        /* s'il y a d'autres éléments, tu voudras peut être les placer
         * dans un layout... J'utilise QVBoxLayout, mais ca peut en être un autre ;)
         */
        QVBoxLayout * newLayout = new QVBoxLayout;
        newLayout->addWidget(edit);
        setLayout(newLayout);
    }
    A partir de là, tu peux utiliser un objet de type MyDialog assez facilement, par exemple (*) sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void MainWindow::showMyDialog(){
        MyDialog dialog;
        dialog.show();
    }
    (*) d'autres solutions sont bien sur envisageables
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Attends : je ne vois pas pourquoi on ne peut pas créer un dialogue de la sorte et pourquoi ça peut bugger... ? A mon sens ça ne sert à rien de dériver : perte de temps pour pas grand chose... Non ?

    Je crée la lineedit et le QDialog indépendemment dans l'entête et après j'assemble les 2 dans le constructeur avec setParent().

    J'ai regardé le ui_MainWindow.h (le source correspondant au formulaire graphique) et c'est bien comme ça qu'on fait, à part qu'il est utilisé l'allocation dynamique : new.

    Ce qui me choque c'est que je fais pourtant pareil mais que quand je ferme le programme avec la croix en haut à droite ça me met "envoyer ou pas le rapport d'erreur". Chose curieuse : le problème disparaît quand dans le destructeur de la MainWindow je mets ceci, juste avant le "delete ui;" :. Bizarre...

    Pour moi, on peut très bien mettre un QDialog parent d'une QLineEdit je ne vois pas en quoi ça gêne... Non ?

    Sinon, quel intérêt d'avoir crée une classe QDialog : concrètement l'objet est un carré vide : c'est la raison pour laquelle je lui rajoute une QLineEdit à laquelle j'ai connecté signaux avec slots auparavant.

    En résumé : si je prends un peu de recul, j'ai crée les 2 indépendamment, je les assemble mais le programme n'est content que si je désassemble les 2 à la fin... Comme si le programme, quand je le ferme, crois que la lineedit est indépendante du QDialog (comme au tout début) la cherche mais ne la trouve pas.

    Au secours... Qué voy a ser je suis perdu !
    Dernière modification par Invité ; 30/11/2013 à 12h14.

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par gizmo27 Voir le message
    Bonjour,

    Attends : je ne vois pas pourquoi on ne peut pas créer un dialogue de la sorte et pourquoi ça peut bugger... ?
    En un mot comme en 100, à cause de la gestion interne des widget.

    Toute la mécanique interne de QWidget consiste à faire en sorte que chaque widget parent va automatiquement essayer d'appeler delete sur chacun de ses enfants et ce, de manière automatique et récursive.
    A mon sens ça ne sert à rien de dériver : perte de temps pour pas grand chose... Non ?
    Une perte de temps

    Selon toi, qu'auras tu le plus facile à faire :
    Créer une classe qui ne dérive pas de QDialog, qui utilise en interne un (pointeur sur un objet de type) QDialog et créer dans ta classe toutes les fonctions qui t'intéresse en faisant en sorte qu'elles appellent celles de QDialog (au besoin avec les adaptations), ou, simplement, faire dériver ta classe de QDialog, de manière à ce qu'elle dispose d'office de toutes les fonctions qui t'intéresse et te contenter de spécialiser les quelques comportements nécessaires

    D'un coté, tu peux t'attendre à devoir créer un grand nombre de fonctions dans ta classe uniquement pour pouvoir appeler les fonctions correspondante du membre de type QDialog, de l'autre, si tu as trois comportement à adapter, tu n'as que trois fonctions à redéfinir

    Je crée la lineedit et le QDialog indépendemment dans l'entête et après j'assemble les 2 dans le constructeur avec setParent().
    Et comme QDialog va appeler delete -- lors de sa destruction -- sur le pointeur de son enfant qui correspond à ton QLineEdit, et que ce pointeur pointe vers un objet qui n'a pas créé avec new, tu vas observer un joli comportement indéfini qui va se transformer en erreur de segmentation à tous les coups.
    J'ai regardé le ui_MainWindow.h (le source correspondant au formulaire graphique) et c'est bien comme ça qu'on fait, à part qu'il est utilisé l'allocation dynamique : new.
    Mais, si tu regardes un tout petit peu d'avantage la classe en question, tu remarqueras qu'elle hérite de QMainWindow

    Et, surtout, tu remarqueras que tout ce que tu places dans la classe ui_MainWindow est géré au travers de pointeurs. Ce n'est pas une coïncidence
    Ce qui me choque c'est que je fais pourtant pareil mais que quand je ferme le programme avec la croix en haut à droite ça me met "envoyer ou pas le rapport d'erreur".
    Parce que tu n'as pas eu recours à l'allocation dynamique pour ton QLineEdit... C'est ce que je viens de t'expliquer
    Chose curieuse : le problème disparaît quand dans le destructeur de la MainWindow je mets ceci, juste avant le "delete ui;" :. Bizarre...
    Parce que tu dis explicitement à ton élément qu'il n'a plus de parent, ce qui a pour résultat de retirer le lien entre le parent et l'enfant qui a été créé lorsque tu as invoqué setParent au début.

    Mais ce n'est pas la bonne manière de pratiquer

    Pour moi, on peut très bien mettre un QDialog parent d'une QLineEdit je ne vois pas en quoi ça gêne... Non ?
    On peut le faire, à condition que l'objet de type QLineEdit ait été créé avec new.

    Mais, essaye d'invoquer setParent sur deux ou trois QLineEdit, avec un code proche de
    QLineEdit * edit1=new QLineEdit;
    QLineEdit * edit2=new QLineEdit;
    QLineEdit * edit3=new QLineEdit;
    QDialog dialog;
    edit1->setParent(&dialog);
    edit2->setParent(&dialog);
    edit3->setParent(&dialog);
    et tu m'en diras des nouvelles
    Sinon, quel intérêt d'avoir crée une classe QDialog : concrètement l'objet est un carré vide : c'est la raison pour laquelle je lui rajoute une QLineEdit à laquelle j'ai connecté signaux avec slots auparavant.
    Parce que c'est une boite vide qui propose malgré tout la possibilité d'avoir un titre et d'avoir la croix de fermeture (au minimum)

    Et, surtout, parce que c'est une classe de base qui est utilisée pour quelques boites de dialogues spécifique (QFileDialog et autres).

    Le but est de pouvoir gérer plusieurs boites de dialogues sans avoir à s'intéresser à ce qu'elles font réellement, en les considérant "simplement" comme des boites de dialogues (sans précision) et de pouvoir invoquer des comportement comme show ou comme exec qui risquent (pour exec en tout cas) de devoir s'adapter au type réel de la boite de dialogue de l'objet sur lequel la fonction est appelée (profiter du polymorphisme, en gros )

    En résumé : si je prends un peu de recul, j'ai crée les 2 indépendamment, je les assemble mais le programme n'est content que si je désassemble les 2 à la fin...
    Et c'est normal cf le début de ma réponse
    Comme si le programme, quand je le ferme, crois que la lineedit est indépendante du QDialog (comme au tout début) la cherche mais ne la trouve pas.
    Au contraire, quand tu fermes ton programme, ton QDialog est détruit, et c'est justement parce qu'il essaye de détruire un enfant que tu n'as pas créé avec new que le programme plante.

    Sans oublier dans tout cela les risques liés à la portée dans laquelle ton QLineEdit est déclaré
    Au secours... Qué voy a ser je suis perdu !
    Et si tu faisais simplement comme je te l'ai expliqué, plutot que d'essayer de faire "à ta sauce"
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Invité
    Invité(e)
    Par défaut
    Merci je vais essayer de tirer ça au clair.

    Donc dans mon cas on ne peut pas ajouter de lineedit dans un QDialog sans faire d'allocation dynamique. Question : pour quelle raison ?

    Et j'ai déjà essayé de passer par un pointeur pour ma lineedit mais c'est bien pire ! J'ai le même message d'erreur qu'à la fin sauf qu'il apparaît au début et le programme plante.

    Penses à te faire payer un gros supplément par DVP pour avoir bossé en heures supp : le samedi c'est 25% en plus

    Bon week-end à toi.
    Cordialement, Gizmo.
    Dernière modification par Invité ; 30/11/2013 à 15h53.

  6. #6
    Invité
    Invité(e)
    Par défaut
    @koala01 : en fait je me suis un peu précipité pour demander pourquoi alors que je penses avoir la réponse, qui est : c'est parce que c'est le gars qui a programmé la fonction setParent() ainsi (après tout si je veux vraiment savoir pourquoi je vais voir la fonction au détail mais je ne suis pas sûr d'en avoir le courage).

    Maintenant je suppose que si ça a été fait comme ça c'est qu'il y a une ou plusieur(s) raison(s).

    Ne connaissant pas les raisons je trouve "dommage" de rendre obligatoire la création d'une QLineEdit par allocation dynamique si on veut l'intégrer à un QDialog.

    Après je suppose que je n'ai pas à ramener ma fraise car les gars qui ont fait Qt s'y connaissent bien plus que moi et qu'ils savent très bien ce qu'ils font.

    C'est juste pour discuter voilà tout.

    Bon week-end. Cordialement, Gizmo.

    PS : et pour ton test ça marche vraiment nickel c'est juste que j'avais connecté les signaux/slots de la QLineEdit AVANT de la créer avec le new, donc forcément...

Discussions similaires

  1. FAQ - imprimer une boîte de dialogue
    Par Eugénie dans le forum MFC
    Réponses: 6
    Dernier message: 27/08/2004, 13h34
  2. [MFC] afficher une boîte de dialogue
    Par bigboomshakala dans le forum MFC
    Réponses: 13
    Dernier message: 10/05/2004, 14h22
  3. [Kylix] Imprimer le contenu d'une boîte de dialogue
    Par cmp-france dans le forum EDI
    Réponses: 13
    Dernier message: 18/10/2003, 20h31
  4. Réponses: 3
    Dernier message: 29/08/2003, 10h57

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