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. [SOLVED] How to destroy parent QWidget window and create&show new QWidget as parent?
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] How to destroy parent QWidget window and create&show new QWidget as parent?

Scheduled Pinned Locked Moved General and Desktop
21 Posts 2 Posters 7.2k Views 1 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.
  • B Offline
    B Offline
    Binary91
    wrote on last edited by
    #1

    Hi,
    I'm a little confused about how to destroy my parent window and create a new one:
    @class window_settings : public QWidget
    {
    Q_OBJECT

    public:
    int columns;
    my_QTextEdit* edit_person[10];
    QPushButton* button_create;

    window_settings(int columns, QWidget* parent = 0);
    

    public slots:
    void createMainWindow();
    };

    class window_main : public QWidget
    {
    Q_OBJECT

    public:
    QTableWidget* table;
    QStringList table_headers_h;

    window_main(int rows, int columns, QStringList &table_headers_h, QWidget* parent = 0);
    

    };

    int main(int argc, char** args)
    {
    FreeConsole();
    QApplication app(argc, args);

    window_settings window_one(10, NULL);
    window_one.show();
    
    app.exec();
    

    return 0;
    }

    window_settings::window_settings(int columns, QWidget* parent) : QWidget(parent)
    {
    this->columns = columns;
    for(int i = 0; i < columns; i++)
    {
    this->edit_person[i] = new my_QTextEdit(my_QTextEdit::TEXT, this);
    }
    button_create = new QPushButton("Create MainWindow", this);
    connect(button_create, SIGNAL(clicked()), this, SLOT(createMainWindow()));
    }

    void window_settings::createMainWindow()
    {
    QStringList table_headers_h;
    for(int i = 0; i < this->columns; i++)
    {
    table_headers_h << this->edit_person[i]->toPlainText();
    }
    this->destroy(true, true);
    window_main window_two(100, this->columns+1, table_headers_h, NULL);
    window_two.show();
    }@
    When I start program, the first window (settings) appears and everything works great. BUT when I click the button "Create MainWindow", the window_main appears 0.5 seconds and closes again with error "program doesn't work correctly anymore.." but program is still running...

    When I create an instance of window_main at first, everything works great, so there is no error in constructor of window_main...

    How do I destroy the first window and create + show the second one correctly?

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      @
      window_main window_two(100, this->columns+1, table_headers_h, NULL);
      window_two.show();
      } <- window_two has ceased to exist here@

      You would need to allocate it on the heap.

      If I may, your design is not the most clean. You should rather separate both. Show your configuration dialog first, then get the information you need from it and construct your main window after.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • B Offline
        B Offline
        Binary91
        wrote on last edited by
        #3

        Hi,
        thank you for your reply!

        Oh well, that sounds logical! I'll test it soon. What I'm asking myself then is: where jumps program after calling window_two.show() ? I mean, after showing first window in int main() it follows the code @app.exec()@ where event loop starts and after destroying first window, program should jump back to int main(), right or wrong? Why don't I have to start a new event loop after showing the second window? Where will program jump after showing it (it must be another scope, otherwise I wouldn't need to create it dynamically)...

        Question 2:
        [quote]You should rather separate both. Show your configuration dialog first, then get the information you need from it and construct your main window after.[/quote]
        Maybe I didn't understand you right, but isn't that exactly what I'm doing?
        At first, I create first dialog (window_settings) in int main(), then I get the user input via button_create --> createMainWindow() and then --> create main_window...
        Maybe I misunderstood you..

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          As long as you don't exit the event loop it continues to run.

          In some way yes, but to keep things clean: it's not your configuration dialog job to create a new MainWindow.

          My proposition:
          @
          ConfigurationDialog dialog;
          dialog.exec();
          int columns = dialog.columns();
          int int rows = dialog.rows();
          MainWindow mw(columns, rows);
          mw.show();
          return app.exec();
          @

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • B Offline
            B Offline
            Binary91
            wrote on last edited by
            #5

            Hi again,
            [quote]As long as you don’t exit the event loop it continues to run[/quote]
            So do you have a guess why my program won't exit after closing the second window in my example?

            [quote]In some way yes, but to keep things clean: it’s not your configuration dialog job to create a new MainWindow.[/quote]
            Ok, that member of QDialogs "exec()" is exaclty the thing I need! Isn't there a way to solve this with to QWidget windows? Is there no way to "create" QWidget window_one, then wait till it's closed and then create QWidget window_two? What do you say to a try like this:
            @QWidget* window_settings = new QWidget();
            window_settings.show();
            eventloop* loop = new QEventLoop;
            connect(window_settings, SIGNAL(destroyed()), loop, SLOT(quit()));
            QWidget* window_main = new QWidget();@
            I will take a look at your advice with QDialog, but I'd also like to know whether this way is a possibility or not AND I really want to know why my example in the previous post won't exit after closing the second window... this is still confusing me much!

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Because you might have destroyed the visual part of your widget but it never closed properly. Your call to destroy should not be there, it's not a function that you usually play with.

              The behavior you are describing reflects exactly the one from QDialog (which is a QWidget)
              Sure you can do it with QWidget, but you are going to rewrite QDialog so why not use it ?

              One thing you should do first is take a look at Qt's tutorials, examples and demos. You'll have a better starting point to write your software

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • B Offline
                B Offline
                Binary91
                wrote on last edited by
                #7

                Ah you've been faster^^
                Well, I read that destroy() is usually managed by QWidgets destructor..
                I'll take a look at the tutorials again, maybe I'll see things more clear after that. What I need is an overview about how to manage a program with multiple windows.
                Should I call it all from the main function and wait until execution call returns (like a star configuration):
                @int main()
                {
                QDialog window_settings;
                window_settings.exec();
                QWidget window_main;
                window_main.show();
                app.exec();
                return 0;
                }@
                Or is it better to do it like in a loop, creating next window from the member functions of first window (like i tried in my first post)...

                Does it depend on what I'm trying to do or is there a general way?

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  There's no simple answer, that will depend on what your software should do.

                  Don't return 0 like that, return what app.exec() returns. Your application may exit giving an error.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • B Offline
                    B Offline
                    Binary91
                    wrote on last edited by
                    #9

                    Ok, I've updated my code, maybe you can take a final look at it and tell me if there's something fundamentally wrong with it or not (I hope not, because it works fine!):
                    @ int main(int argc, char** args)
                    {
                    FreeConsole();
                    QApplication app(argc, args);

                    QStringList table_headers_h;
                    table_headers_h << "Amount";
                    for(int i = 1; i < 11; i++)
                    {
                      table_headers_h << "Person "+QString::number(i);
                    }
                    
                    window_main* window_m = new window_main(100, 11, table_headers_h, NULL);
                    window_m->show();
                    window_m->settings();
                    

                    return app.exec();
                    }

                    void window_main::settings()
                    {
                    window_settings* window_s = new window_settings(10, this);
                    window_s->exec();
                    }

                    window_settings::window_settings(int columns, QWidget* parent) : QDialog(parent)
                    {
                    this->parent = parent; // save the main_windows pointer so I can update it later from this QDialog instance

                    for(int i = 0; i < columns; i++)
                    {
                      this->edit_person[i] = new my_QTextEdit(my_QTextEdit::TEXT, this);
                    }
                    button_create = new QPushButton("Create", this);
                    button_create->setGeometry(QRect(5, (5+columns*30), 150, 30));
                    connect(button_create, SIGNAL(clicked()), this, SLOT(createMainWindow()));
                    

                    }

                    void window_settings::createMainWindow()
                    {
                    QStringList table_headers_h;
                    QString header_item;
                    table_headers_h << "Amount";
                    for(int i = 0; i < this->columns; i++)
                    {
                    header_item = (this->edit_person[i]->toPlainText() != "") ? this->edit_person[i]->toPlainText() : "Person "+QString::number(i+1);
                    table_headers_h << header_item;
                    }
                    ((window_main*)this->parent)->table_headers_h = table_headers_h; // downcasting QWidget pointer to window_main...
                    ((window_main*)this->parent)->table->setHorizontalHeaderLabels(table_headers_h);
                    this->close();
                    }@

                    I have moved the creation of QDialog to a function, so I can open that setting_window by button click on main window later again...

                    Three questions left:

                    1. is that code ok or still fundamentally wrong?
                    2. I always use "FreeConsole();" to avoid opening command box... problem is, it still opens for 0.5s and that isn't pretty... how can I avoid this flicker?
                    3. Is it better to downcast via qobject_cast or can I do it like I did with simply using ((window_main*)parent) pointer?

                    Thank you for paying attention one last time to that topic :)

                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      It might be working but it's not clean at all.

                      First thing, what does FreeConsole do there ?

                      Widgets already have a parent method to retrieve it, no need for a member variable.

                      Don't use c-style cast with QObject derived class, use qobject_cast.

                      BUT, that design is wrong: keep the responsibilities separated.

                      Your setting widget should just handle the settings, it's not its job to modify the content of your main window. The main window itself should handle that.

                      Take the case where you change some stuff in your main window, something as little as just one variable name, now you have to look at three different places to change that. I know that with modern IDE it's not a real problem but the fact is that your code is going to be a nightmare to maintain.

                      Please take the time to look at Qt's examples, they show nicely how to do what you want.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      0
                      • B Offline
                        B Offline
                        Binary91
                        wrote on last edited by
                        #11

                        [quote]First thing, what does FreeConsole do there ?[/quote]As I already mentioned, I need it to close the command box that opens every time I start my program. I read in google that this is an easy way to hide the command box, but the problem is the flicker at the beginning, because it still opens for 0.5s and I see it appearing (what sucks and I need a solution to avoid it).
                        Any solutions for that?
                        [quote]Widgets already have a parent method to retrieve it, no need for a member variable.[/quote]Oh yes, that's right :) So many great functions provided by Qt classes!! I will spend lots of days finding new good features that make my life easier :)
                        [quote]Don’t use c-style cast with QObject derived class, use qobject_cast.[/quote]Ok...
                        [quote]Your setting widget should just handle the settings, it’s not its job to modify the content of your main window. The main window itself should handle that.Take the case where you change some stuff in your main window, something as little as just one variable name, now you have to look at three different places to change that. I know that with modern IDE it’s not a real problem but the fact is that your code is going to be a nightmare to maintain.[/quote]Oh yes, good aspect! I'm sure that at the latest when my program grows I'd have to spend lots of time thinking about opportunities to make code more dynamic like a layout, where I only have to change things in one sheet...
                        Thank you for that advice, that will help me much while planing future applications!!
                        What I additionally did is including the QDialog into main_window class as a member with a function to get input:
                        @class window_settings : public QDialog
                        {
                        Q_OBJECT

                        public:
                        int columns;
                        my_QTextEdit* edit_person[10];
                        QPushButton* button_create;

                        window_settings(int columns, QWidget* parent = 0);
                        QStringList getInputTextEdit();
                        

                        };

                        class window_main : public QWidget
                        {
                        Q_OBJECT

                        public:
                        window_settings* win_settings;
                        QTableWidget* table;
                        QStringList table_headers_v, table_headers_h;
                        QListWidget* list;
                        QPushButton *button_settings, *button_calculate;

                        window_main(int rows, int columns, QStringList &table_headers_h, QWidget* parent = 0);
                        void updateAll();
                        

                        public slots:
                        void settings();
                        void calculate();
                        };

                        int main(int argc, char** args)
                        {
                        FreeConsole();
                        QApplication app(argc, args);

                        QStringList table_headers_h;
                        table_headers_h << "Amount";
                        for(int i = 1; i < 11; i++)
                        {
                          table_headers_h << "Person "+QString::number(i);
                        }
                        
                        window_main* win_main = new window_main(100, 11, table_headers_h, NULL);
                        win_main->win_settings = new window_settings(10, win_main);
                        win_main->show();
                        win_main->settings();
                        

                        return app.exec();
                        }

                        window_main::window_main(int rows, int columns, QStringList &table_headers_h, QWidget* parent) : QWidget(parent)
                        {
                        //....
                        button_calculate = new QPushButton("Calculate", this);
                        connect(button_calculate, SIGNAL(clicked()), this, SLOT(calculate()));

                        button_settings = new QPushButton("Settings", this);
                        connect(button_settings, SIGNAL(clicked()), this, SLOT(settings()));
                        

                        }

                        void window_main::settings()
                        {
                        this->win_settings->exec();
                        }@
                        How do you think about this? QDialog opens now each time user clicks window_main button "Settings".
                        In window_main function "updateAll()" (not shown in code), it calls QDialog function getInputTextEdit() and retrieves the stored inputs to update itsself...
                        Good or bad way?

                        1 Reply Last reply
                        0
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          Do you have QT += console somewhere in you pro file ? If so, just remove it.

                          @
                          QStringList table_headers_h;
                          table_headers_h << "Amount";
                          for(int i = 1; i < 11; i++)
                          {
                          table_headers_h << "Person "+QString::number(i);
                          }
                          @

                          Should rather be in your widget constructor.
                          If you don't want to, then you should pass your QStringList as a const reference.

                          You still have a memory leak, you never delete win_main.

                          Are you still modifying window_main from your settings dialog ?

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          1 Reply Last reply
                          0
                          • B Offline
                            B Offline
                            Binary91
                            wrote on last edited by
                            #13

                            [quote]Do you have QT += console somewhere in you pro file ?[/quote]I'm directly compiling. I did a little program that directly calls g+++ with the needed includes, so what do I have to change to avoid displaying the command line box?

                            [quote]Should rather be in your widget constructor.[/quote]Thats right, it is there, I just moved it to main() for posting it, because I did not want to show the whole constructor to shorten the code & comment.

                            [quote]You still have a memory leak, you never delete win_main.[/quote]Oh yes, I'll fix that, but where should I do that? The only way would be to connect window closing signal to a function that deletes win_main, right? But closing the window is not the only way to close an application, so how can I avoid the memory leak if someone closes the application via taskbar / taskmanager or something else? Is there also a genereal QApplication closing signal or something else?

                            [quote]Are you still modifying window_main from your settings dialog ?[/quote]No, I have two functions now:

                            • function A (win_main member) calls function B (win_settings member) and retrieves the userinput from win_settings. So win_main updates itsself...
                            1 Reply Last reply
                            0
                            • SGaistS Offline
                              SGaistS Offline
                              SGaist
                              Lifetime Qt Champion
                              wrote on last edited by
                              #14

                              Why don't you use qmake ?

                              You have several possibilities but since your program is pretty simple:

                              @
                              window_main win_main(100, 11, table_headers_h);
                              @

                              is enough

                              Interested in AI ? www.idiap.ch
                              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                              1 Reply Last reply
                              0
                              • B Offline
                                B Offline
                                Binary91
                                wrote on last edited by
                                #15

                                I thought Qt is known for good care about automatically deleting dynamically created QWidgets? I strongly use the QWidget* parent method to initialize each new QWidget as a child of win_main...
                                So the only thing compiler has to do is caring about deleting win_main...
                                Why doesn't this happen after closing the event-loop?
                                Where would I have to manually call it's destructor then? I don't know...

                                1 Reply Last reply
                                0
                                • SGaistS Offline
                                  SGaistS Offline
                                  SGaist
                                  Lifetime Qt Champion
                                  wrote on last edited by
                                  #16

                                  Yes it does but it can't do everything:

                                  @
                                  window_main* window_m = new window_main(100, 11, table_headers_h); << window_m is allocated on the heap, with no parent, so it's outside of Qt's scope.
                                  window_m->show();

                                  return app.exec();
                                  @

                                  Either use:

                                  @
                                  window_main window_m(100, 11, table_headers_h);
                                  window_m.show();
                                  return app.exec();
                                  @

                                  or

                                  window_main* window_m = new window_main(100, 11, table_headers_h, NULL);
                                  window_m->show();

                                  int ret = app.exec();
                                  delete mainwindw_main;
                                  return ret;
                                  @

                                  Interested in AI ? www.idiap.ch
                                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                  1 Reply Last reply
                                  0
                                  • B Offline
                                    B Offline
                                    Binary91
                                    wrote on last edited by
                                    #17

                                    Ah there we go. Then it is a little bit the way I already tried to go.
                                    First:
                                    [quote]window_main* window_m = new window_main(100, 11, table_headers_h, NULL); [/quote]That is exaclty what I'm doing, take a look at my constructor:
                                    @window_main::window_main(int rows, int columns, QStringList &header, QWidget* parent = 0) : QWidget(parent)
                                    {
                                    ...
                                    }@
                                    I don't pass the NULL pointer directly by calling constructor but I declare constructor with it as default value... should be the same, isn't it?

                                    [quote]int ret = app.exec(); delete mainwindw_main; return ret;[/quote]That is exactly what I already thought of... So I still have to delete the parent QWidget manually? Then that will be the only way, and for that reason I should really take care of all my widgets to be childs of at least one parent, so I'm always safe when I just delete one QWidget.. is that the right way?

                                    1 Reply Last reply
                                    0
                                    • SGaistS Offline
                                      SGaistS Offline
                                      SGaist
                                      Lifetime Qt Champion
                                      wrote on last edited by
                                      #18

                                      Yes it is, but that was just a simplified copy paste of your code to show the possibilities.

                                      Not the parent but parentless widgets (which generally ends up being the "parent"), unless you set the WA_DeleteOnClose flag on that widget.

                                      Interested in AI ? www.idiap.ch
                                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                      1 Reply Last reply
                                      0
                                      • B Offline
                                        B Offline
                                        Binary91
                                        wrote on last edited by
                                        #19

                                        Ok, I think I got it now..
                                        I'll do it like you recommended and delete the "parent" (parentless aka NULL pointer) after app.exec() returned and finally, I'll return the returned value from app.exec()...

                                        Thank you so much for your help and endurance!

                                        1 Reply Last reply
                                        0
                                        • SGaistS Offline
                                          SGaistS Offline
                                          SGaist
                                          Lifetime Qt Champion
                                          wrote on last edited by
                                          #20

                                          Well, in this case, there's no real reason to use a pointer for your widget. Just allocate it on the stack and let it get destroyed when going out of scope.

                                          Interested in AI ? www.idiap.ch
                                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                          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