Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Qt] Changer le contenu d'une fenêtre

Sujet résolu
    14 janvier 2019 à 23:10:42

    Bonjour,

    Je débute avec Qt et je ne trouve pas comment faire pour changer le contenu d'une fenêtre sans ouvrir une nouvelle fenêtre avec un bouton puis revenir au premier contenu. Par exemple au départ il y aurait 2 boutons ("Page 1" et "Page 2") sur la fenêtre puis lorsque qu'on appuierait sur le premier bouton ("Page 1") le contenue de la fenêtre changerait le contenu est sans importance ici malgré la présence d'un bouton "Retour" et quand on appuierait dessus on reviendrait au premier contenu avec les 2 boutons.

    Comment je pourrais faire cela ?

    Merci d'avance pour votre aide !

    • Partager sur Facebook
    • Partager sur Twitter
      15 janvier 2019 à 9:18:29

      Hello !

      Un QStackWidget est bien adapté dans ce cas là. Tu créés tes différentes vues dans des widgets différents et tu les ajoutes à ton stack widget. Ensuite tu peux faire des setCurrentIndex en fonction de la page que tu veux afficher. ;)

      • Partager sur Facebook
      • Partager sur Twitter
        15 janvier 2019 à 11:04:01

        Bonjour Maluna,

        Oui avec un QStackWidget j'ai réussi a acceder a ma "Page 1" mais comment faire pour faire le bouton "Retour" ?

        Car le QStackWidget est dans la class de ma fenêtre principale (la page menu avec les 2 boutons "Page 1" et  "Page 2") donc je ne peux pas faire de "setCurrentIndex" via le nouveau contenu ?

        • Partager sur Facebook
        • Partager sur Twitter
          15 janvier 2019 à 11:33:29

          Après libre à toi de l'ajouter dans le stack widget (ou non d'ailleurs). :)

          C'est à toi de coder le bouton retour sur ta page principale, je ne pense pas que tu aies de trucs tout fait dans Qt. Tu peux avoir des connexions de ce style :

          connect(backButton, &QPushButton::clicked, this, &MainWindow::showMainPage);

          Avec un showMainPage qui fait un setCurrentIndex(0) si ta page principale est dans ton stackWidget. :)

          • Partager sur Facebook
          • Partager sur Twitter
            15 janvier 2019 à 11:57:25

            Mon QStackWidget ainsi que mes différentes pages je les créés dans le main ? Car il faut que je puisse faire un setCurrentIndex depuis nimporte quelle page. ^^'

            Est-ce qu'il est possible de faire des SLOTS pour accéder à chaque page dans mon main pour qu'ils soient utilisables depuis nimporte quelle class (1 class par page) ?

            Si oui comment je fais cela ?

            -
            Edité par TeKFun 15 janvier 2019 à 12:06:08

            • Partager sur Facebook
            • Partager sur Twitter
              15 janvier 2019 à 12:02:43

              C'est ta classe qui a le stack widget qui gère ça.

              Je te conseille d'avoir un bouton de retour sous ton StackWidget et pas dedans s'il est commun aux différentes pages. Tu le caches dans le showMainPage, tu l'affiche dès que l'on bascule sur une autre page.

              C'est pas aux classes qui représentent les différentes pages de gérer le changement. :)

              Et dans le cas où le bouton de retour est dans chaque page (ce que je ne te conseille pas mais imaginons s'il doit être différent pour chaque page), alors c'est la classe de la page qui doit émettre un signal back qui dans tous les cas doit être géré par ta classe qui a le stack widget (qu'il soit récupéré directement depuis le bouton ou depuis les classes des pages).

              J'espère avoir été clair. ^^

              -
              Edité par Maluna34 15 janvier 2019 à 12:06:33

              • Partager sur Facebook
              • Partager sur Twitter
                15 janvier 2019 à 15:15:20

                Pour résumer voici ce que je voudrais faire sous forme de schéma

                Donc une class mainPage, une class page1 et une class page2

                mainPage aurait deux boutons un qui afficherait la page1 et un autre bouton qui afficherais la page2

                page1 et page2 on un bouton retour qui affiche la mainPage

                Ces 3 pages seraient dans un QStackWidget pour les afficher avec un setCurrentIndex.

                Maintenant ou est-ce que je doit mettre ce QStackWidget (dans le main? dans une autre class? dans une des 3 pages ?)

                Et comment je fais pour changer de page sachant que les "connect" des boutons sont dans leurs class respective ?

                Désolé je reformule :-° car j'ai compris dans le principe ce que tu me dis mais je ne vois pas comment faire principalement pour émettre un signalback qui doit être géré par la class qui a le stackWidget
                • Partager sur Facebook
                • Partager sur Twitter
                  15 janvier 2019 à 15:46:57

                  J'avais bien compris ce que tu veux faire. ^^"

                  Où tu dois mettre le stack widget je ne sais pas moi. Ca dépend d'où il se situe dans ton application. Ca peut très bien être dans ta MainWindow comme ailleurs. Le stack widget est un widget donc tu peux le mettre où tu veux. Mais il va contenir les 3 pages donc il n'est pas dans l'une d'entre elles.

                  Après pour la gestion, je t'ai conseillé d'avoir le bouton de retour en dehors de ton stack widget. Mais dans le cas où il est dans ta page 1 et ta page 2 tu peux connecter un signal à un signal donc tes classes page1 et page2 doivent retransmettre le signal :

                  class Page1 : public QWidget
                  {
                  public:
                     Page1()
                     {
                        connect(backButton, &QPushButton::clicked, this, &Page1::back);
                     }
                  
                  signals;
                     void back();
                  };

                  Et dans ta classe principale :

                  connect(page1, &Page1::back, this, [this]() {
                     stackWidget->setCurrentIndex(0);
                  });
                  
                  connect(page2, &Page2::back, this, [this]() {
                     stackWidget->setCurrentIndex(0);
                  });

                  Pareil pour ta mainPage tu récupères les signaux des boutons et tu as un truc comme :

                  connect(mainPage, &MainPage::pageClicked, this, [this](int page) {
                     stackWidget->setCurrentIndex(page);
                  });

                  En considérant, par exemple, que tu MainPage t'émet un signal en transmettant le numéro de la page :

                  void pageClicked(int page);

                  -
                  Edité par Maluna34 15 janvier 2019 à 15:50:06

                  • Partager sur Facebook
                  • Partager sur Twitter
                    15 janvier 2019 à 15:52:34

                    D'accord ^^'

                    Je ne comprend pas ton code sur le deuxième screen mais je vais essayer ce soir et je te redis ou j'en suis en tout cas merci beaucoup de ton aide =D

                    Si j'ai bien compris le SLOT est "stackWidget->setCurrentIdex(page)" ?

                    Mais les signaux de doivent-ils pas avoir le même type de paramètre que les SLOTS ?

                    ici tu as mis un SIGNAL sans paramètre et un SLOT qui prend un "int" en paramètre, ou alors je n'ai pas compris ^^"

                    -
                    Edité par TeKFun 15 janvier 2019 à 16:03:37

                    • Partager sur Facebook
                    • Partager sur Twitter
                      15 janvier 2019 à 16:04:42

                      Je connecte le signal à une lambda dans le cas où il n'y a qu'une ligne, mais tu peux très bien le connecter à une méthode de classe comme tu sais le faire. :)

                      connect(page1, &Page1::back, this, [this]() {
                         stackWidget->setCurrentIndex(0);
                      });

                      =

                      {
                         connect(page1, &Page1::back, this, &Classe::showMainPage);
                      }
                      
                      void Classe::showMainPage()
                      {
                         stackWidget->setCurrentIndex(0);
                      }

                      C'est pareil. ;)

                      EDIT: Si dans le cas de pageClicked j'ai bien mis que ce signal envoie un int :

                      class MainPage
                      {
                      signals:
                         void pageClicked(int page);
                      };

                      -
                      Edité par Maluna34 15 janvier 2019 à 16:07:28

                      • Partager sur Facebook
                      • Partager sur Twitter
                        15 janvier 2019 à 16:08:54

                        Okey je vois un peu mieux j'essai de faire ça ce soir quand je rentre je te redis merci beaucoup =D


                        EDIT : 

                        Le problème est que je ne vois pas comment mettre la MainPage dans le stackWidget puisque le stackWidget est dans la class MainPage.

                        Et je ne vois pas comment faire une class juste pour le stackWidget et les différentes pages.

                        Voici mon code :

                        FenPrinc.cpp (équivalent de la MainPage)

                        #include "FenPrinc.h"
                        #include <iostream>
                        
                        
                        FenPrinc::FenPrinc() : QMainWindow()
                        {
                            stack = new QStackedWidget;
                            fenetre1 = new FenSec;
                        
                            zoneCentrale = new QWidget;
                            layout = new QFormLayout(this);
                        
                            nom = new QLineEdit;
                            prenom = new QLineEdit;
                            age = new QLineEdit;
                            bouton = new QPushButton("Changer fenetre");
                        
                            layout->addRow("&Nom : ", nom);
                            layout->addRow("&Prenom : ", prenom);
                            layout->addRow("&Age : ", age);
                            layout->addWidget(bouton);
                        
                        
                            stack->addWidget(fenetre1);
                            zoneCentrale->setLayout(layout);
                            setCentralWidget(zoneCentrale);
                            stack->setCurrentIndex(0);
                            connect(bouton, SIGNAL(clicked()), this, SLOT(changeFen()));
                            connect(fenetre1, SIGNAL(back()), this, SLOT(returnMainWindow()));
                        }
                        
                        void FenPrinc::changeFen()
                        {
                            stack->setCurrentIndex(1);
                            setCentralWidget(stack);
                        }
                        
                        void FenPrinc::returnMainWindow()
                        {
                            std::cout << "tessqegsezgegt" << std::endl;
                            stack->setCurrentIndex(0);
                            setCentralWidget(stack);
                        }
                        
                        

                        FenPrinc.h

                        #ifndef FENPRINC_H
                        #define FENPRINC_H
                        
                        #include <QMainWindow>
                        #include <QtWidgets>
                        #include "FenSec.h"
                        #include "FenSec1.h"
                        #include <iostream>
                        
                        class FenPrinc : public QMainWindow
                        {
                            Q_OBJECT
                        
                            public:
                                FenPrinc();
                            public slots:
                                void changeFen();
                                void returnMainWindow();
                            private:
                                QWidget *zoneCentrale;
                                QStackedWidget *stack;
                                FenSec *fen1;
                                QFormLayout *layout;
                                QLineEdit *nom;
                                QLineEdit *prenom;
                                QLineEdit *age;
                                QPushButton *bouton;
                                FenSec *fenetre1;
                            signals:
                                void pageClicked(int page);
                        };
                        
                        #endif // FENPRINC_H
                        



                        FenSec.cpp

                        #include "FenSec.h"
                        #include <iostream>
                        
                        FenSec::FenSec() : QWidget()
                        {
                            layout = new QFormLayout;
                            label = new QLabel("C'est la première fenetre secondaire");
                            backBouton = new QPushButton("Retour 1");
                        
                            layout->addRow(label);
                            layout->addRow(backBouton);
                        
                            setLayout(layout);
                        
                            connect(backBouton, SIGNAL(clicked()), this, SLOT(sendBack()));
                        }
                        
                        void FenSec::sendBack()
                        {
                            emit back();
                            std::cout << "tessqegsezgegt" << std::endl;
                        }
                        

                        FenSec.h

                        #ifndef FENSEC_H
                        #define FENSEC_H
                        
                        #include <QtWidgets>
                        
                        class FenSec : public QWidget
                        {
                            Q_OBJECT
                        
                            public:
                                FenSec();
                            private:
                                QFormLayout *layout;
                                QLabel *label;
                                QPushButton *backBouton;
                            public slots:
                                void sendBack();
                            signals:
                                void back();
                        };
                        
                        #endif // FENSEC_H
                        

                        main.cpp

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

                        Merci de ton aide !

                        -
                        Edité par TeKFun 16 janvier 2019 à 1:31:35

                        • Partager sur Facebook
                        • Partager sur Twitter
                          17 janvier 2019 à 9:37:05

                          Tu ne dois pas changer le central widget de ta fenêtre principale. C'est le page du stack widget qui a besoin d'être changée.

                          FenPrinc::FenPrinc() : QMainWindow()
                          {
                              stack = new QStackedWidget;
                           
                              stack->addWidget(mainPage);
                              stack->addWidget(fenetre1);
                              stack->addWidget(fenetre2);
                          
                              setCentralWidget(stack);
                          
                              connect(mainPage, &MainPage::pageChanged, this, [this](int page) {
                                stack->setCurrentIndex(page);
                              });
                          
                              connect(fenetre1, &FenSec::back, this, [this]() {
                                stack->setCurrentIndex(0);
                              });
                          }

                          Autre petit point aussi : tu n'as pas forcément besoin du slot sendBack() dans FenSec tu peux directement connecter clicked au signal back().

                          -
                          Edité par Maluna34 17 janvier 2019 à 9:41:29

                          • Partager sur Facebook
                          • Partager sur Twitter
                            17 janvier 2019 à 12:57:12

                            Tu peux aussi utiliser un combo box plutôt qu'un bouton, c'est pratique si tu as plusieurs sous-fenêtre, un truc dans le genre:

                            #ifndef MULTI_VIEW_HEADER_INCLUDED
                            #define MULTI_VIEW_HEADER_INCLUDED
                            #include<QComboBox>
                            #include<QStackedWidget>
                            
                            class MultiView
                            {
                            	Q_OBJECT
                            	
                            public:
                            
                            	explicit MultiView(QWidget * owner = nullptr);
                                    virtual ~MultiView() = default;
                            	
                            	void addWidget(QString const & label,QWidget * view);
                            	
                            private:
                            	
                            	QComboBox * selector_;
                            	QStackedWidget * display_;
                            };
                            #endif // MULTI_VIEW_HEADER_INCLUDED

                            Et le Cpp:

                            #include"multiview.h"
                            #include<QLayout>
                            
                            MultiView::MultiView(QWidget * owner)
                                :QWidget{owner}
                                ,selector_{new QComboBox{this}}
                                ,display_{new QStackedWidget{this}}
                            {
                                // geometry
                                auto main = new QVBoxLayout{};
                                main->addWidget(selector_);
                                main->addWidget(display_);
                                setLayout(main);
                            
                                // connexions
                                using Cptr = void (QComboBox::*)(int);
                                using Sptr = void (QStackedWidget::*)(int);	
                                Cptr cptr = &QComboBox::currentIndexChanged;
                                Sptr sptr = &QStackedWidget::setCurrentIndex;
                                connect(selector_,cptr,display_,sptr);
                            }
                            
                            void MultiView::addWidget(QString const & label,QWidget * view)
                            {
                                display_->AddWidget(view);
                                selector_->addItem(label);	
                            }
                            


                            Quand tu sélectionnes une ligne dans le ComboBox, ça te bascule sur la fenêtre correspondante. Ici, j'ai pris un ComboBox parce que c'est le plus simple, mais tu peux faire la même chose avec un QListWidget, un QTreeView...

                            • Partager sur Facebook
                            • Partager sur Twitter
                            Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
                              19 janvier 2019 à 14:48:46

                              J'ai réussi a faire une class pour gérer mon stackWidget ainsi que mes fenêtres, ensuite quand j'appuis sur le bouton un signal est bien émit (en tout cas le programme rentre bien dans le slot) mais je ne comprend pas pourquoi ce n'est pas récupéré par ma class qui gère le stackWidget

                              FenPrinc.cpp

                              #include "FenPrinc.h"
                              #include <iostream>
                              
                              FenPrinc::FenPrinc() : QWidget()
                              {
                                  layout = new QFormLayout(this);
                                  nom = new QLineEdit;
                                  prenom = new QLineEdit;
                                  age = new QLineEdit;
                                  bouton = new QPushButton("Changer fenetre");
                              
                                  layout->addRow("&Nom : ", nom);
                                  layout->addRow("&Prenom : ", prenom);
                                  layout->addRow("&Age : ", age);
                                  layout->addWidget(bouton);
                              
                                  connect(bouton, SIGNAL(clicked()), this, SLOT(emiTest()));
                              }
                              
                              void FenPrinc::emiTest()
                              {
                                  std::cout << "clicked" << std::endl;
                                  emit test();
                              }

                              FenPrinc.h

                              #ifndef FENPRINC_H
                              #define FENPRINC_H
                              
                              #include <QMainWindow>
                              #include <QtWidgets>
                              #include "FenSec.h"
                              #include "FenSec1.h"
                              
                              #include <iostream>
                              
                              class FenPrinc : public QWidget
                              {
                                  Q_OBJECT
                              
                                  public:
                                      FenPrinc();
                                  public slots:
                                      void emiTest();
                                  private:
                                      QFormLayout *layout;
                                      QLineEdit *nom;
                                      QLineEdit *prenom;
                                      QLineEdit *age;
                                      QPushButton *bouton;
                                      FenSec *fenetre1;
                                  signals:
                                      void test();
                              };
                              
                              #endif // FENPRINC_H



                              SetStackWindow.cpp

                              #include "SetStackWindow.h"
                              #include <iostream>
                              
                              SetStackWindow::SetStackWindow() : QMainWindow()
                              {
                                  fenetre = new FenPrinc;
                                  fenetre1 = new FenSec;
                              
                                  stack = new QStackedWidget;
                              
                                  stack->insertWidget(0, fenetre);
                                  stack->insertWidget(1, fenetre1);
                              
                                  stack->setCurrentIndex(0);
                                  setCentralWidget(stack);
                              
                                  connect(fenetre, &FenPrinc::emiTest, this, [this] {
                                      std::cout << "la fenetre doit changer" << std::endl;
                                      //stack->setCurrentIndex(1);
                                  });
                              
                              }



                              SetStackWindow.h

                              #ifndef SETSTACKWINDOW_H
                              #define SETSTACKWINDOW_H
                              
                              #include <QtWidgets>
                              #include "FenPrinc.h"
                              #include "FenSec.h"
                              
                              class SetStackWindow : public QMainWindow
                              {
                                  public:
                                      SetStackWindow();
                                  private:
                                      QStackedWidget *stack;
                                      FenPrinc *fenetre;
                                      FenSec *fenetre1;
                              };
                              
                              #endif // SETSTACKWINDOW_H

                              J'ai pensé qu'il fallait inclure le "SetStackWindow.h" dans FenPrinc.h mais quand je le fais ça me fais plein d'erreur que je ne comprend pas 


                              int21h

                              Désolé mais je ne vais pas utiliser ta technique tout simplement car tu utilise des choses que je ne connais pas du tout ^^' mais merci quand même et si tu as une réponse a mon problème que je viens de mettre je t'écoute sans souci merci 

                              (je suis a mes début avec le c++ et Qt)



                              -
                              Edité par TeKFun 19 janvier 2019 à 14:51:53

                              • Partager sur Facebook
                              • Partager sur Twitter
                                19 janvier 2019 à 16:41:23

                                Hello,

                                TeKFun a écrit:

                                J'ai pensé qu'il fallait inclure le "SetStackWindow.h" dans FenPrinc.h mais quand je le fais ça me fais plein d'erreur que je ne comprend pas

                                C'est normal, SetStackWindow.h a besoin de connaître la classe FenPrinc et FenPrinc.h a besoin de connaître SetStackWindow. Du coup ba c'est le bordel ^^. Mais la conception ne va pas.

                                L'héritage est bizarre. Ta fenêtre principale hérite de QWidget et ta classe SetStackWindow hérite de QMainWindow. Fait tout simplement hériter ta classe pour la fenêtre principale de QMainWindow. Et pour le QStackWidget, gère le depuis ta fenêtre principale et si besoin créé une classe custom qui hérite de QStackWidget.

                                -
                                Edité par Guit0Xx 19 janvier 2019 à 16:42:19

                                • Partager sur Facebook
                                • Partager sur Twitter

                                ...

                                  19 janvier 2019 à 18:39:28

                                  Salut, 

                                  J'ai essayé en faisant hériter ma fenêtre principale de QMainWindow mais ça ne change rien :/

                                  Et je ne peux pas laisser mon QStackWidget dans ma fenêtre principale car si je fais cela je ne peux pas mettre ma fenêtre principale dedans et puis je trouve que c'est plus clair dans le code d'avoir une class par fenêtre et une class pour les gérer

                                  Apres je peux me tromper je débute :p

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    20 janvier 2019 à 15:12:37

                                    Il y a une erreur de signal lorsque tu fais ta connexion dans SetStackWindow.cpp.

                                    Le signal de la classe FenPrinc c'est test, pas emiTest.

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      20 janvier 2019 à 17:37:32

                                      Génial ça fonctionne enfin, merci beaucoup a tous je mets en sujet résolu !
                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      [Qt] Changer le contenu d'une fenêtre

                                      × 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