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. QFileDialog from child window closes the application

QFileDialog from child window closes the application

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 5 Posters 2.0k 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.
  • X Offline
    X Offline
    XapaJIaMnu
    wrote on last edited by
    #1

    Hey guys,

    This is a cross-post from SO with no answers:

    I'm new to QT and I'm having issues when calling QFileDialog from a child window. My app is relatively simple. I have one prompt widget that gets user input and then runs show on its parent. This is my main:

    int main(int argc, char *argv[]) {
        QApplication a(argc, argv);
    
        ParentWidjet w(nullptr);
    
        ChildWidget input(&w);
        input.show();
    
        return a.exec();
    }
    

    This is the relevant section of the child widget:

    ChildWidget::ChildWidget(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::InputPrompt){
        ui->setupUi(this);
        this->setParent(parent);
    }
    ...
    void ChildWidget::on_imagesSelect_clicked() {
        inputFilepath = QFileDialog::getExistingDirectory(static_cast<ParentWidget *>(this->parent()), QCoreApplication::translate("main", "Open directory"), "./", QFileDialog::ShowDirsOnly);
        ui->inputPath->setPlainText(inputFilepath);
        std::cout << "y u exit" << std::endl;
    }
    //Setup and show the parent
    void ChildWidget::on_buttonBox_accepted() {
        static_cast<ParentWidjet *>(this->parent())->setup(inputFilepath, outputFilepath);
        static_cast<ParentWidjet *>(this->parent())->show();
    }
    

    For some reason when QFileDialog is called, closing it with either OK or Cancel closes both the parent and the child. If I don't use it, but click the OK button of the child, which calls the on_buttonBox_accepted() function, the child closes and the parent widget appears as expected. If I don't pass the parent widget to the child widget in the main, QFileDialog no longer closes the child widget when running. I tried changing the parent of QFileDialog to this or to nullptr but that didn't help.

    Any ideas? Is this expected or am I use the API wrong?

    Cheers,

    Nick

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

      Hi and welcome to devnet,

      Why are you using the parent of your widget ?
      Why a static cast on it ?

      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
      2
      • X XapaJIaMnu

        Hey guys,

        This is a cross-post from SO with no answers:

        I'm new to QT and I'm having issues when calling QFileDialog from a child window. My app is relatively simple. I have one prompt widget that gets user input and then runs show on its parent. This is my main:

        int main(int argc, char *argv[]) {
            QApplication a(argc, argv);
        
            ParentWidjet w(nullptr);
        
            ChildWidget input(&w);
            input.show();
        
            return a.exec();
        }
        

        This is the relevant section of the child widget:

        ChildWidget::ChildWidget(QWidget *parent) :
            QDialog(parent),
            ui(new Ui::InputPrompt){
            ui->setupUi(this);
            this->setParent(parent);
        }
        ...
        void ChildWidget::on_imagesSelect_clicked() {
            inputFilepath = QFileDialog::getExistingDirectory(static_cast<ParentWidget *>(this->parent()), QCoreApplication::translate("main", "Open directory"), "./", QFileDialog::ShowDirsOnly);
            ui->inputPath->setPlainText(inputFilepath);
            std::cout << "y u exit" << std::endl;
        }
        //Setup and show the parent
        void ChildWidget::on_buttonBox_accepted() {
            static_cast<ParentWidjet *>(this->parent())->setup(inputFilepath, outputFilepath);
            static_cast<ParentWidjet *>(this->parent())->show();
        }
        

        For some reason when QFileDialog is called, closing it with either OK or Cancel closes both the parent and the child. If I don't use it, but click the OK button of the child, which calls the on_buttonBox_accepted() function, the child closes and the parent widget appears as expected. If I don't pass the parent widget to the child widget in the main, QFileDialog no longer closes the child widget when running. I tried changing the parent of QFileDialog to this or to nullptr but that didn't help.

        Any ideas? Is this expected or am I use the API wrong?

        Cheers,

        Nick

        kshegunovK Offline
        kshegunovK Offline
        kshegunov
        Moderators
        wrote on last edited by kshegunov
        #3

        When all windows are closed, by default your application is going to quit as well. This is controllable through a property in QGuiApplication.

        Read and abide by the Qt Code of Conduct

        X 1 Reply Last reply
        1
        • kshegunovK kshegunov

          When all windows are closed, by default your application is going to quit as well. This is controllable through a property in QGuiApplication.

          X Offline
          X Offline
          XapaJIaMnu
          wrote on last edited by
          #4

          Thank you for the replies!

          @SGaist said in QFileDialog from child window closes the application:

          Hi and welcome to devnet,

          Why are you using the parent of your widget ?
          Why a static cast on it ?

          I just played around with it, trying to make it work. Using this has the same behaviour. The static cast was necessary because the parent is a superclass of QWidget... I think. There was a compiler error without it.

          @kshegunov said in QFileDialog from child window closes the application:

          When all windows are closed, by default your application is going to quit as well. This is controllable through a property in QGuiApplication.

          When the file Dialog window appears, there is still a window open in the background which is my widget. It is not by any means the last window closed... Or it shouldn't it be. I will try the property later when I have access to a computer.

          My point is that if the child widget does not receive a pointer to the parent in the constructor, the file dialog does not close it.

          I'll give an update in a few hours.

          Cheers,

          Nick

          jsulmJ 1 Reply Last reply
          0
          • mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Hi
            I was wondering, since ChildWidget is a QDialog, why dont you use its blocking feature ?
            like

            int main(int argc, char *argv[]) {
                QApplication a(argc, argv);
            
                ParentWidget w(nullptr);
            
               ChildWidget input;
               if (  input.exec() == QDialog::accepted)   // exec() blocks execution until ok/cancel. unlike show()
               {
                 w.setup(input.inputFilepath, input.outputFilepath); // assuming these are public
                 w.show()
              } else 
             {  // user closed or pressed cancelled
               ... what u want to do..
             }
            
                return a.exec();
            }
            
            X 1 Reply Last reply
            2
            • mrjjM mrjj

              Hi
              I was wondering, since ChildWidget is a QDialog, why dont you use its blocking feature ?
              like

              int main(int argc, char *argv[]) {
                  QApplication a(argc, argv);
              
                  ParentWidget w(nullptr);
              
                 ChildWidget input;
                 if (  input.exec() == QDialog::accepted)   // exec() blocks execution until ok/cancel. unlike show()
                 {
                   w.setup(input.inputFilepath, input.outputFilepath); // assuming these are public
                   w.show()
                } else 
               {  // user closed or pressed cancelled
                 ... what u want to do..
               }
              
                  return a.exec();
              }
              
              X Offline
              X Offline
              XapaJIaMnu
              wrote on last edited by
              #6

              @mrjj said in QFileDialog from child window closes the application:

              Hi
              I was wondering, since ChildWidget is a QDialog, why dont you use its blocking feature ?
              like

              int main(int argc, char *argv[]) {
                  QApplication a(argc, argv);
              
                  ParentWidget w(nullptr);
              
                 ChildWidget input;
                 if (  input.exec() == QDialog::accepted)   // exec() blocks execution until ok/cancel. unlike show()
                 {
                   w.setup(input.inputFilepath, input.outputFilepath); // assuming these are public
                   w.show()
                } else 
               {  // user closed or pressed cancelled
                 ... what u want to do..
               }
              
                  return a.exec();
              }
              

              This worked like a charm, thank you! Could you tell me why the previous solution I had was closing all the windows as soon as the file dialog closed? Is it undefined behaviour or..?

              Cheers,
              Nick

              mrjjM 1 Reply Last reply
              0
              • X XapaJIaMnu

                @mrjj said in QFileDialog from child window closes the application:

                Hi
                I was wondering, since ChildWidget is a QDialog, why dont you use its blocking feature ?
                like

                int main(int argc, char *argv[]) {
                    QApplication a(argc, argv);
                
                    ParentWidget w(nullptr);
                
                   ChildWidget input;
                   if (  input.exec() == QDialog::accepted)   // exec() blocks execution until ok/cancel. unlike show()
                   {
                     w.setup(input.inputFilepath, input.outputFilepath); // assuming these are public
                     w.show()
                  } else 
                 {  // user closed or pressed cancelled
                   ... what u want to do..
                 }
                
                    return a.exec();
                }
                

                This worked like a charm, thank you! Could you tell me why the previous solution I had was closing all the windows as soon as the file dialog closed? Is it undefined behaviour or..?

                Cheers,
                Nick

                mrjjM Offline
                mrjjM Offline
                mrjj
                Lifetime Qt Champion
                wrote on last edited by mrjj
                #7

                @XapaJIaMnu
                Hi
                Nope, the other solution was not that kinky.
                Normally FileDialog::getExistingDirectory will not just close other widgets.
                so my best bet is what @kshegunov wrote about.
                The quitOnLastWindowClosed property that is default true.
                You can test this if you still have old code.

                int main(int argc, char *argv[]) {
                    QApplication a(argc, argv);
                
                    ParentWidjet w(nullptr);
                
                    ChildWidget input(&w);
                    input.show();
                
                    return a.exec();
                  int me=100; // place break point here
                }
                

                and try code. if it stops there as soon as you press Ok, it was the reason.

                One note about the casting:
                static_cast<ParentWidjet *>(this->parent())->setup(inputFilepath, outputFilepath);
                static_cast<ParentWidjet *>(this->parent())->show();
                this is pretty unsafe as static_cast does not check if its ok to do so
                so with QWidgets we have a better cast qobject_cast
                and a better version would be like

                void ChildWidget::on_buttonBox_accepted() {
                ParentWidjet * myparent=qobject_cast<ParentWidjet *> ( parent() );
                if (myparent)   // always check if not null
                {
                 myparent->setup(inputFilepath, outputFilepath);
                 myparent->show();
                }
                }
                

                This applies to any case where you give it a custom QWidget and reading it back as a base pointer
                (QWidget *).
                Then you can safely cast and check this way.
                in short, no static_cast on QWidgets/QObjects :)

                X 1 Reply Last reply
                2
                • mrjjM mrjj

                  @XapaJIaMnu
                  Hi
                  Nope, the other solution was not that kinky.
                  Normally FileDialog::getExistingDirectory will not just close other widgets.
                  so my best bet is what @kshegunov wrote about.
                  The quitOnLastWindowClosed property that is default true.
                  You can test this if you still have old code.

                  int main(int argc, char *argv[]) {
                      QApplication a(argc, argv);
                  
                      ParentWidjet w(nullptr);
                  
                      ChildWidget input(&w);
                      input.show();
                  
                      return a.exec();
                    int me=100; // place break point here
                  }
                  

                  and try code. if it stops there as soon as you press Ok, it was the reason.

                  One note about the casting:
                  static_cast<ParentWidjet *>(this->parent())->setup(inputFilepath, outputFilepath);
                  static_cast<ParentWidjet *>(this->parent())->show();
                  this is pretty unsafe as static_cast does not check if its ok to do so
                  so with QWidgets we have a better cast qobject_cast
                  and a better version would be like

                  void ChildWidget::on_buttonBox_accepted() {
                  ParentWidjet * myparent=qobject_cast<ParentWidjet *> ( parent() );
                  if (myparent)   // always check if not null
                  {
                   myparent->setup(inputFilepath, outputFilepath);
                   myparent->show();
                  }
                  }
                  

                  This applies to any case where you give it a custom QWidget and reading it back as a base pointer
                  (QWidget *).
                  Then you can safely cast and check this way.
                  in short, no static_cast on QWidgets/QObjects :)

                  X Offline
                  X Offline
                  XapaJIaMnu
                  wrote on last edited by
                  #8

                  @mrjj said in QFileDialog from child window closes the application:

                  @XapaJIaMnu
                  Hi
                  Nope, the other solution was not that kinky.
                  Normally FileDialog::getExistingDirectory will not just close other widgets.
                  so my best bet is what @kshegunov wrote about.
                  The quitOnLastWindowClosed property that is default true.
                  You can test this if you still have old code.

                  Yeah, you are right @kshegunov tweaking that property also fixes the issue. However I don't understand how it was triggered since the documentation says.

                  If this property is true, the applications quits when the last visible primary window (i.e. window with no parent) is closed.

                  However my dialog window clearly has a parent. Anyways, problem solved

                  One note about the casting:
                  static_cast<ParentWidjet *>(this->parent())->setup(inputFilepath, outputFilepath);
                  static_cast<ParentWidjet *>(this->parent())->show();
                  this is pretty unsafe as static_cast does not check if its ok to do so
                  so with QWidgets we have a better cast qobject_cast
                  and a better version would be like

                  void ChildWidget::on_buttonBox_accepted() {
                  ParentWidjet * myparent=qobject_cast<ParentWidjet *> ( parent() );
                  if (myparent)   // always check if not null
                  {
                   myparent->setup(inputFilepath, outputFilepath);
                   myparent->show();
                  }
                  }
                  

                  This applies to any case where you give it a custom QWidget and reading it back as a base pointer
                  (QWidget *).
                  Then you can safely cast and check this way.
                  in short, no static_cast on QWidgets/QObjects :)

                  I was under the impression that if the programmer is certain about the type, they should use static_cast for performance reasons, as opposed to dynamic_cast or qobject_cast, which are much safer. I got rid of all my casting shizz anyways since i no longer need it.

                  Thank you all for the help and the explanations!

                  Cheers,

                  Nick

                  1 Reply Last reply
                  0
                  • X XapaJIaMnu

                    Thank you for the replies!

                    @SGaist said in QFileDialog from child window closes the application:

                    Hi and welcome to devnet,

                    Why are you using the parent of your widget ?
                    Why a static cast on it ?

                    I just played around with it, trying to make it work. Using this has the same behaviour. The static cast was necessary because the parent is a superclass of QWidget... I think. There was a compiler error without it.

                    @kshegunov said in QFileDialog from child window closes the application:

                    When all windows are closed, by default your application is going to quit as well. This is controllable through a property in QGuiApplication.

                    When the file Dialog window appears, there is still a window open in the background which is my widget. It is not by any means the last window closed... Or it shouldn't it be. I will try the property later when I have access to a computer.

                    My point is that if the child widget does not receive a pointer to the parent in the constructor, the file dialog does not close it.

                    I'll give an update in a few hours.

                    Cheers,

                    Nick

                    jsulmJ Offline
                    jsulmJ Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @XapaJIaMnu said in QFileDialog from child window closes the application:

                    The static cast was necessary because the parent is a superclass of QWidget

                    This is not possible. Your parent class can't be a superclass/baseclass of QWidget, it is for sure other way around.
                    So this cast is not needed:

                    inputFilepath = QFileDialog::getExistingDirectory(static_cast<ParentWidget *>(this->parent()), QCoreApplication::translate("main", "Open directory"), "./", QFileDialog::ShowDirsOnly);
                    

                    I find the way you're doing it wrong: the child should NOT call show on the parent. Instead, it should emit a signal when it's done. Before calling show on child you connect this signal to a slot in your parent. In this slot you call show() then. Reason: child should not define the behaviour of the parent directly (decoupling).

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    X 1 Reply Last reply
                    3
                    • jsulmJ jsulm

                      @XapaJIaMnu said in QFileDialog from child window closes the application:

                      The static cast was necessary because the parent is a superclass of QWidget

                      This is not possible. Your parent class can't be a superclass/baseclass of QWidget, it is for sure other way around.
                      So this cast is not needed:

                      inputFilepath = QFileDialog::getExistingDirectory(static_cast<ParentWidget *>(this->parent()), QCoreApplication::translate("main", "Open directory"), "./", QFileDialog::ShowDirsOnly);
                      

                      I find the way you're doing it wrong: the child should NOT call show on the parent. Instead, it should emit a signal when it's done. Before calling show on child you connect this signal to a slot in your parent. In this slot you call show() then. Reason: child should not define the behaviour of the parent directly (decoupling).

                      X Offline
                      X Offline
                      XapaJIaMnu
                      wrote on last edited by
                      #10

                      @jsulm said in QFileDialog from child window closes the application:

                      @XapaJIaMnu said in QFileDialog from child window closes the application:

                      The static cast was necessary because the parent is a superclass of QWidget

                      This is not possible. Your parent class can't be a superclass/baseclass of QWidget, it is for sure other way around.

                      Yes, my bad, it's a subclass.

                      So this cast is not needed:

                      inputFilepath = QFileDialog::getExistingDirectory(static_cast<ParentWidget *>(this->parent()), QCoreApplication::translate("main", "Open directory"), "./", QFileDialog::ShowDirsOnly);
                      

                      I find the way you're doing it wrong: the child should NOT call show on the parent. Instead, it should emit a signal when it's done. Before calling show on child you connect this signal to a slot in your parent. In this slot you call show() then. Reason: child should not define the behaviour of the parent directly (decoupling).

                      I have gone with the answer suggested by @mrjj . I don't quite understand what you mean by connecting the signal. Could you illustrate with some code?

                      Cheers,

                      Nick

                      jsulmJ 1 Reply Last reply
                      0
                      • X XapaJIaMnu

                        @jsulm said in QFileDialog from child window closes the application:

                        @XapaJIaMnu said in QFileDialog from child window closes the application:

                        The static cast was necessary because the parent is a superclass of QWidget

                        This is not possible. Your parent class can't be a superclass/baseclass of QWidget, it is for sure other way around.

                        Yes, my bad, it's a subclass.

                        So this cast is not needed:

                        inputFilepath = QFileDialog::getExistingDirectory(static_cast<ParentWidget *>(this->parent()), QCoreApplication::translate("main", "Open directory"), "./", QFileDialog::ShowDirsOnly);
                        

                        I find the way you're doing it wrong: the child should NOT call show on the parent. Instead, it should emit a signal when it's done. Before calling show on child you connect this signal to a slot in your parent. In this slot you call show() then. Reason: child should not define the behaviour of the parent directly (decoupling).

                        I have gone with the answer suggested by @mrjj . I don't quite understand what you mean by connecting the signal. Could you illustrate with some code?

                        Cheers,

                        Nick

                        jsulmJ Offline
                        jsulmJ Offline
                        jsulm
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        @XapaJIaMnu You define a signal in the child. You define a slot in the parent. You connect the signal to the slot:

                        int main(int argc, char *argv[]) {
                          QApplication a(argc, argv);
                        
                          ParentWidjet w(nullptr);
                        
                          ChildWidget input(&w);
                          connect(&input, &ChildWidget::someSignal, &w, &ParentWidjet::someSlot);
                          input.show();
                        
                          return a.exec();
                          int me=100; // place break point here
                          return 0;
                        }
                        

                        https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        3

                        • Login

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