Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved [c++] opening window B by clicking a button on window A

    General and Desktop
    c++ button window
    4
    8
    186
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • U
      Uchi last edited by Uchi

      I have 2 windows, BusRegistration and start ( The main window )

      I open start window simply by

      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          start w;
          w.show();
          return a.exec();
      }
      

      My goal is to show BusRegistration window by clicking on a button from start window but to do that I need a Bus object that the button function from start.cpp can access .

      Declaring the bus object inside start.cpp results in an error.
      The following code shows the bus window for a brief until it's deallocated because the function terminates so it doesn't work either

      void start::on_BusRegistration_clicked() {
          BusRegister bus;
          bus.show();
      }
      

      Apologies for the basic question but I couldn't find an appropriate solution for this.

      1 Reply Last reply Reply Quote 0
      • C
        ChrisW67 last edited by

        This is generic C++ object lifetime knowledge.

        Allocate the BusRegister object on the heap, not the stack.
        At its simplest:

        void start::on_BusRegistration_clicked() {
            BusRegister *bus = new BusRegister(this);
            // if you want the object deleted when the visible widget is closed then
            bus->setAttribute(Qt::WA_DeleteOnClose);
            // otherwise you will create new one for each button click and keep them all. 
            // They will all be deleted with the `start` object because of QObject parenting.
            bus->show();
        }
        

        If that window will be opened and closed a lot, or you need to access it outside this slot then you may store the pointer as a member variable in the launching start object:

        // modify the header 
        private:
        BusRegister *m_bus;
        
        // modify the constructor to initialise the new member
        start::start(QWidget *p = nullptr)
            : QWidget(p)
            , m_bus(nullptr)
        { ... } 
        
        // and the slot
        void start::on_BusRegistration_clicked() {
            if (!m_bus) {
                m_bus = new BusRegister(this);
            }
            m_bus->show();
        }
        
        U 1 Reply Last reply Reply Quote 1
        • C
          ChrisW67 last edited by

          This is generic C++ object lifetime knowledge.

          Allocate the BusRegister object on the heap, not the stack.
          At its simplest:

          void start::on_BusRegistration_clicked() {
              BusRegister *bus = new BusRegister(this);
              // if you want the object deleted when the visible widget is closed then
              bus->setAttribute(Qt::WA_DeleteOnClose);
              // otherwise you will create new one for each button click and keep them all. 
              // They will all be deleted with the `start` object because of QObject parenting.
              bus->show();
          }
          

          If that window will be opened and closed a lot, or you need to access it outside this slot then you may store the pointer as a member variable in the launching start object:

          // modify the header 
          private:
          BusRegister *m_bus;
          
          // modify the constructor to initialise the new member
          start::start(QWidget *p = nullptr)
              : QWidget(p)
              , m_bus(nullptr)
          { ... } 
          
          // and the slot
          void start::on_BusRegistration_clicked() {
              if (!m_bus) {
                  m_bus = new BusRegister(this);
              }
              m_bus->show();
          }
          
          U 1 Reply Last reply Reply Quote 1
          • U
            Uchi @ChrisW67 last edited by Uchi

            what about if I want the main window object ( w ) to be visible in BusRegister.cpp so I can change the main window by clicking a button in the subwindow ( basically the reverse of the previous situation )

            int main(int argc, char *argv[])
            {
                QApplication a(argc, argv);
                start w;
                w.show();
                return a.exec();
            }
            

            in BusRegister.cpp i want to do something like this but w obviously can't be accessed in BusRegister, 'return' is the button name

            void BusRegister::on_Return_clicked() {
            	this->close();
            	w.hide();
            }
            
            Gaobo 1 Reply Last reply Reply Quote 0
            • Gaobo
              Gaobo @Uchi last edited by

              @Uchi maybe u can use signal/slot .

              class BusRegister
              {
                  ...
              signals:
                  void sgnClose();
              };
              
              class start
              {
              private:
                  BusRegister *m_bus;
              };
              
              // connect the signal/slot
              connect(m_bus, &BusRegister::sgnClose, this, &start::close);
              
              // when you clicked the button, emit the signal "sgnClose"
              void BusRegister::on_Return_clicked() {
              	this->close();
                      emit sgnClose();
              }
              
              U 1 Reply Last reply Reply Quote 1
              • U
                Uchi @Gaobo last edited by Uchi

                @Gaobo said in [c++] opening window B by clicking a button on window A:

                connect(m_bus, &BusRegister::sgnClose, this, &start::close);

                Where should i write this?
                I assumed that i should place it here

                start::start(QWidget* parent)
                    : QMainWindow(parent) , m_bus(nullptr)
                {
                    ui.setupUi(this);
                    connect(m_bus, &BusRegister::sgnClose, this, &start::close);
                }
                

                but it doesn't really close or hide the main window

                JonB 1 Reply Last reply Reply Quote 0
                • JonB
                  JonB @Uchi last edited by JonB

                  @Uchi said in [c++] opening window B by clicking a button on window A:

                  doesn't really close or hide the main window

                  Yes, you put the connect() in the right place. [Correct class, but apparently not right place. See the Note below.]

                  What does "really" mean here? Either the main window closes or it does not, how does it not "really" close??

                  I know nothing about what this "bus" is, but do you ever receive this signal?

                  connect(m_bus, &BusRegister::sgnClose, this, [this]() { qDebug() << "sgnClose received"; close();  } );
                  

                  Note: in this/your code, m_bus must have been set to a BusRegister instance at the time the connect() is called. But you are calling it from a constructor with m_bus(nullptr) and no parameter to set it to a BusRegister. That won't work.... Either create and pass in a BusRegister or delay the call to the connect() until you do so.

                  U 1 Reply Last reply Reply Quote 1
                  • U
                    Uchi @JonB last edited by Uchi

                    @JonB
                    so basically i can't create the signal because the object is initialized as null

                    so I decided to declare the m_bus before setting up the connection and removing the previous declaration.
                    It works now, thanks.

                    start::start(QWidget* parent)
                        : QMainWindow(parent) , m_bus(nullptr)
                    {
                        m_bus = new BusRegister(this);
                        ui.setupUi(this);
                        connect(m_bus, &BusRegister::sgnShow, this, &start::show); //i changed it to close to show
                    }
                    
                    
                    JonB 1 Reply Last reply Reply Quote 0
                    • JonB
                      JonB @Uchi last edited by

                      @Uchi
                      Correct! At the time the connect() statement is issued both the signal & slot objects must be set to the instances to be connected, that's what connect() does. Changing either of the objects later to an instance has no effect on the earlier connect().

                      1 Reply Last reply Reply Quote 1
                      • First post
                        Last post