Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Show and hide parent window (QWidget) from child (QDialog)
Forum Updated to NodeBB v4.3 + New Features

Show and hide parent window (QWidget) from child (QDialog)

Scheduled Pinned Locked Moved General and Desktop
13 Posts 5 Posters 12.6k Views 3 Watching
  • 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.
  • Y Offline
    Y Offline
    Yossi
    wrote on last edited by
    #1

    Hi,
    I'm developing a tool for KDE that allows user to toggle between two windows (Qwidget and QDialog)

    When "parentJump" slot is triggered it shows myQdialog window and hides MainWindow . It works good.

    //mainWindow.cpp
    void MainWindow::parentJump(){
    cout << "Jump to qdialog window" <<endl <<flush;
    myQdialog->show(); //myQdialog = new mySetupDialog()
    this->hide();
    }

    When I'm trying to jump back to mainWindow it doesn't work. I tried to do it by invokeMethod and simply use parent->show

    //mySetupDialog.cpp
    void mySetupDialog::jump(){
    cout << "jumping to main window" << endl ;
    // parent->show(); // doesn't work
    // QMetaObject::invokeMethod(parent,"show"); // doesn't work
    this->hide();
    }

    Can you please tell me how is the right way to implement it?

    Thanks,
    Yossi.

    1 Reply Last reply
    0
    • JeroentjehomeJ Offline
      JeroentjehomeJ Offline
      Jeroentjehome
      wrote on last edited by
      #2

      Hi,
      The parent pointer is a QObject pointer, not a Widget!! So do a qobject_cast to change it into a QWidget pointer and use the show.
      That might do the trick!

      Greetz, Jeroen

      1 Reply Last reply
      0
      • Y Offline
        Y Offline
        Yossi
        wrote on last edited by Yossi
        #3

        Hi Jeroen,

        Thanks for your fast response.

        parent is already Qwidget pointer

        mySetupDialog::mySetupDialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::mySetupDialog)
        {
        ...
        }

        Anyhow, I tried your suggestion and it wont work

        ((QWidget*)parent)->show();
        ERROR: invalid use of member (did you forget the ‘&’ ?)

        1 Reply Last reply
        0
        • J Offline
          J Offline
          Jumetor
          wrote on last edited by
          #4

          Hi Jossi,

          I solved my problem with the signals and slots like this:

          in child.h
          signals:
          void Want2Close();

          in child.cpp
          void child::on_btnClose_clicked()
          {
          this->close();
          emit Want2Close();
          }

          in parent.cpp on a QpushButton

          child *child1 = new child;
          connect(child1,&child::Want2Close,this,&MainWindow::show);
          this->hide();
          child1->show();
          
          Y 1 Reply Last reply
          1
          • Chris KawaC Offline
            Chris KawaC Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @Yossi said:

            ((QWidget*)parent)->show();
            ERROR: invalid use of member (did you forget the ‘&’ ?)

            parent() is a function, so you need to give it a parameter list, even if it's empty: (QWidget*)parent()->show().

            But you don't have to do that at all. There are also parentWidget() and window() methods that give you your widget's parent widget and your widget's top level widget respectively. Just remember to check if what they return is not null before you try to call anything on it.

            1 Reply Last reply
            1
            • J Jumetor

              Hi Jossi,

              I solved my problem with the signals and slots like this:

              in child.h
              signals:
              void Want2Close();

              in child.cpp
              void child::on_btnClose_clicked()
              {
              this->close();
              emit Want2Close();
              }

              in parent.cpp on a QpushButton

              child *child1 = new child;
              connect(child1,&child::Want2Close,this,&MainWindow::show);
              this->hide();
              child1->show();
              
              Y Offline
              Y Offline
              Yossi
              wrote on last edited by
              #6

              @Jumetor

              I tried it and I got the following errors:
              error: cannot call member function ‘void child::Want2Close()’ without object
              error: lvalue required as unary ‘&’ operand

              Any idea why?

              Thanks.

              J 1 Reply Last reply
              0
              • Chris KawaC Offline
                Chris KawaC Offline
                Chris Kawa
                Lifetime Qt Champion
                wrote on last edited by
                #7

                Want2Close() is not a static memberfunction so you cant call it on a class name like that. You need to call it on an instance of your class, e.g. something like child1->Want2Close(), but you need to post the code that actually errors out for us to help.

                Btw. Please surround code blocks with ```. It will make it a lot easier for us to read here.

                1 Reply Last reply
                0
                • Y Yossi

                  @Jumetor

                  I tried it and I got the following errors:
                  error: cannot call member function ‘void child::Want2Close()’ without object
                  error: lvalue required as unary ‘&’ operand

                  Any idea why?

                  Thanks.

                  J Offline
                  J Offline
                  Jumetor
                  wrote on last edited by
                  #8

                  @Yossi ,

                  here my exemple :
                  https://mega.nz/#!TxtXXLhD!BxXcBix1ObvFEik7w8x9rdISmdz9g_zAi7zRZ8NJrT0

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    ambershark
                    wrote on last edited by ambershark
                    #9

                    My guess is your pointer to your "parent" is not your mainwindow for some reason.

                    Try putting in something like this:

                    void mySetupDialog::jump()
                    {
                       QObject *p = this;
                       do 
                       {
                          p = p->parent();
                       } while (p->parent() != NULL);
                    
                       QMainWindow *mw = qobject_cast<QMainWindow *>(p);
                       if (!mw)
                       {
                          // couldnt find main window
                       }
                       else
                       {
                          mw->show();
                          hide();
                       }
                    }
                    

                    Now if that works, I would figure out why mw != parent to prevent further issues. Once you figure that out you can ditch this loop method.

                    This also assumes QMainWIndow is your top level widget, which it should be. If it's not, add pointer cast testing with qobject_cast into your loop till you find your main window.

                    My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                    1 Reply Last reply
                    0
                    • Chris KawaC Offline
                      Chris KawaC Offline
                      Chris Kawa
                      Lifetime Qt Champion
                      wrote on last edited by Chris Kawa
                      #10

                      OMG, guys, you're complicating this beyond reason.

                      @Jumetor You're basically reinventing the wheel - a dialog. Also, you're leaking memory (Form instance).
                      @ambershark Loops and casts are total overkill. All you need is window()->show(), but even that is unnecessary here.

                      The child shouldn't even know about its parent and it's not its role to show or hide it. "Sniffing" for a parent of concrete type is just evil. What if top most class changes one day?

                      Here's a simple example (I ommited layouts and such for simplicity):

                      #include <QApplication>
                      #include <QMainWindow>
                      #include <QDialog>
                      #include <QPushButton>
                      
                      class Form : public QDialog {
                      public:
                          Form() {
                              auto closeBtn = new QPushButton("Close", this);
                              connect(closeBtn, &QPushButton::clicked, this, &Form::accept);
                          }
                      };
                      
                      class MainWindow : public QMainWindow {
                      public:
                          MainWindow() {
                              auto openBtn = new QPushButton("Open child", this);
                              connect(openBtn, &QPushButton::clicked, this, &MainWindow::showDialog);
                          }
                          void showDialog() {
                              hide();
                              Form form;
                              form.exec();
                              show();
                          }
                      };
                      
                      
                      int main(int argc, char *argv[])
                      {
                          QApplication a(argc, argv);
                          MainWindow w;
                          w.show();
                      
                          return a.exec();
                      }
                      
                      J A 2 Replies Last reply
                      0
                      • Chris KawaC Chris Kawa

                        OMG, guys, you're complicating this beyond reason.

                        @Jumetor You're basically reinventing the wheel - a dialog. Also, you're leaking memory (Form instance).
                        @ambershark Loops and casts are total overkill. All you need is window()->show(), but even that is unnecessary here.

                        The child shouldn't even know about its parent and it's not its role to show or hide it. "Sniffing" for a parent of concrete type is just evil. What if top most class changes one day?

                        Here's a simple example (I ommited layouts and such for simplicity):

                        #include <QApplication>
                        #include <QMainWindow>
                        #include <QDialog>
                        #include <QPushButton>
                        
                        class Form : public QDialog {
                        public:
                            Form() {
                                auto closeBtn = new QPushButton("Close", this);
                                connect(closeBtn, &QPushButton::clicked, this, &Form::accept);
                            }
                        };
                        
                        class MainWindow : public QMainWindow {
                        public:
                            MainWindow() {
                                auto openBtn = new QPushButton("Open child", this);
                                connect(openBtn, &QPushButton::clicked, this, &MainWindow::showDialog);
                            }
                            void showDialog() {
                                hide();
                                Form form;
                                form.exec();
                                show();
                            }
                        };
                        
                        
                        int main(int argc, char *argv[])
                        {
                            QApplication a(argc, argv);
                            MainWindow w;
                            w.show();
                        
                            return a.exec();
                        }
                        
                        J Offline
                        J Offline
                        Jumetor
                        wrote on last edited by
                        #11

                        Hi @Chris-Kawa ,

                        Thank you for your example. I do not know. I use every time a QWidget for my forms.
                        In my example, I can avoid the memory leak?

                        1 Reply Last reply
                        0
                        • Chris KawaC Offline
                          Chris KawaC Offline
                          Chris Kawa
                          Lifetime Qt Champion
                          wrote on last edited by Chris Kawa
                          #12

                          @Jumetor You can set a Qt::WA_DeleteOnClose attribute on your form using setAttribute(). This would delete the Form instance when it is closed. But the code widow->show() in the Form will not show the main window. It will show the top most widget containing the caller. In other words it'll just show itself. The form really shouldn't try to show the main window. The main window should show the dialog and wait for it to close then show up again, like in my example. The dependencies are much smaller this way, as only one class knows about another and not both referring to each other.

                          Btw. If you never used QDialog I suggest you start doing so. That's what it's there for.

                          1 Reply Last reply
                          0
                          • Chris KawaC Chris Kawa

                            OMG, guys, you're complicating this beyond reason.

                            @Jumetor You're basically reinventing the wheel - a dialog. Also, you're leaking memory (Form instance).
                            @ambershark Loops and casts are total overkill. All you need is window()->show(), but even that is unnecessary here.

                            The child shouldn't even know about its parent and it's not its role to show or hide it. "Sniffing" for a parent of concrete type is just evil. What if top most class changes one day?

                            Here's a simple example (I ommited layouts and such for simplicity):

                            #include <QApplication>
                            #include <QMainWindow>
                            #include <QDialog>
                            #include <QPushButton>
                            
                            class Form : public QDialog {
                            public:
                                Form() {
                                    auto closeBtn = new QPushButton("Close", this);
                                    connect(closeBtn, &QPushButton::clicked, this, &Form::accept);
                                }
                            };
                            
                            class MainWindow : public QMainWindow {
                            public:
                                MainWindow() {
                                    auto openBtn = new QPushButton("Open child", this);
                                    connect(openBtn, &QPushButton::clicked, this, &MainWindow::showDialog);
                                }
                                void showDialog() {
                                    hide();
                                    Form form;
                                    form.exec();
                                    show();
                                }
                            };
                            
                            
                            int main(int argc, char *argv[])
                            {
                                QApplication a(argc, argv);
                                MainWindow w;
                                w.show();
                            
                                return a.exec();
                            }
                            
                            A Offline
                            A Offline
                            ambershark
                            wrote on last edited by
                            #13

                            @Chris-Kawa I didn't give him that loop for production reasons. I gave it to him to check to see why his parent widget wasn't matching the main window (assuming it wasn't). If you read my whole post you would see I told him to "ditch this loop method".

                            This was just to help him figure out what was going on not to leave in for actual usage in a program.

                            And if the parent changed some day then the if (!mw) would catch that. Assuming he left this code in which again I recommended against. :)

                            My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                            1 Reply Last reply
                            0

                            • Login

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved