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. Open a dialog from other than mainwindow
Forum Updated to NodeBB v4.3 + New Features

Open a dialog from other than mainwindow

Scheduled Pinned Locked Moved Solved General and Desktop
14 Posts 4 Posters 1.2k 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.
  • B Offline
    B Offline
    Bryan Kelly
    wrote on last edited by
    #5

    here is the code. Begin with the list of files that exist after the project has been created, then the two dialogs d2 and d3 have been created.

    open_files.png

    next is mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    
    QT_BEGIN_NAMESPACE
    namespace Ui {
    class MainWindow;
    }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
        
           // dialog d2 needs to have a pointer to d3 so if d3 is already
           // open it can just show it.  Then d2 needs the ability to
           // inform main (as in mainwindow.h, this object) that d3 has been created.
        QDialog * get_d3_pointer();
        void      put_d3_pointer( QDialog * temp );
    
    private slots:
        void on_pb_open_d2_clicked(bool checked);
    
        void on_pb_open_d3_clicked();
    
    private:
        Ui::MainWindow *ui;
        QDialog * d2 = NULL;
        QDialog * d3 = NULL;
    };
    #endif // MAINWINDOW_H
    

    next is mainwindow.cpp

    #include "mainwindow.h"
    #include "./ui_mainwindow.h"
    #include "qdialog.h"
     
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::on_pb_open_d2_clicked(bool checked)
    {
        if( d2 == NULL )
           d2 = new( QDialog );
        d2->show();
        d2->setWindowTitle( "dialog D2");
           // When dialog d2 is opened, copy the local 'this' pointer to d2 so that d2 can
           // determine if d3 has been created.
           // The next line has the message:  No member named 'set_main_dialog_pointer' in 'QDialog'
           // True, but, object d2 has that function declared.  This is to call it.
        d2->set_main_dialog_pointer( this );
    }
    
    
    void MainWindow::on_pb_open_d3_clicked()
    {
        if( d3 == NULL )
           d3 = new( QDialog );
        d3->show();
        d3->setWindowTitle( "dialog D3");
    }
    
       // cannot get the above code to work so have not completed these items.
    QDialog * MainWindow::get_d3_pointer()
    {
        return d3;
    }
    void      MainWindow::put_d3_pointer( QDialog * temp )
    {
        d3 = temp;
    }
    
    

    next is d2.h

    #ifndef D2_H
    #define D2_H
    
    #include <QDialog>
    
    namespace Ui {
    class d2;
    }
    
    class d2 : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit d2(QWidget *parent = nullptr);
        ~d2();
           // The main dialog can call this function, provide its "this" pointer,
           // so this object, d2, can get the value of main's d3 pointer.
        void set_main_dialog_pointer( QDialog * temp );
    
    private slots:
        void on_pb_open_d3_2_clicked();
        QDialog * main_window_ptr = NULL;
    
    private:
        Ui::d2 *ui;
        QDialog * local_d3_ptr;
        
    };
    
    #endif // D2_H
    

    next is d2.cpp

    #include "d2.h"
    #include "ui_d2.h"
    #include "mainwindow.h"
    
    d2::d2(QWidget *parent)
        : QDialog(parent)
        , ui(new Ui::d2)
    {
        ui->setupUi(this);
    }
    
    d2::~d2()
    {
        delete ui;
    }
       // This is the second push button that can create/open dialog d3.
    void d2::on_pb_open_d3_2_clicked()
    {
           // get main's pointer to d3.  It may or may not be valid
           // The next line has the error message:
           // No member 'get_d3_pointer' in 'QDialog'
           // True, but that function is declared in mainwindow.h
           // which should be pointed to my main_window_ptr.
        local_d3_ptr = main_window_ptr->get_d3_pointer();
        if( local_d3_ptr == NULL )
        {
            local_d3_ptr = new( local_d3_ptr );
               // next line has same errors noted a few lines up.
            main_window_ptr->put_d3_pointer( local_d3 );
        }
    }
    
    void d2::set_main_dialog_pointer( QDialog * temp )
    {
        main_window_ptr = temp;
    }
    
       // from post by Pl45m4
       // changed m_dialog to match this code with d3, the pointer to the dialog
       // to be opened.  Many errors here.  The text of the first is:
       // A type specifier is required for all declarations.
                                                     
    connect(p, &QPushButton::clicked, this, [=](){
        
        if (local_d3)
            local_d3->show();
    });
    
    

    &&&&&&&&&&&&&&&&&&&&&&&&
    files d3.h and d3.cpp have not yet been edited. The dialog has been opened from main window, but not from d2, which is the goal.

    mainwidow.ui has two pushbuttons as shown below, the upper left corner of that dialog

    main_window.png

    dialog d2 has just one added pushbutton, to open d3. It is named pb_open_d3_2

    d2_dialog.png

    files d3.h, d3.cpp, and d3.ui have not been changed after being created by Qt Creator.

    &&&&&&&&&&&&&&&&&
    Finally, to restate the goal of this app: The main dialog has the ability to open and show dialog d3. That is just standard code. The goal is to provide dialog d2 with the ability to open and/or show dialog d3.

    Pl45m4P 1 Reply Last reply
    0
    • B Bryan Kelly

      here is the code. Begin with the list of files that exist after the project has been created, then the two dialogs d2 and d3 have been created.

      open_files.png

      next is mainwindow.h

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      
      QT_BEGIN_NAMESPACE
      namespace Ui {
      class MainWindow;
      }
      QT_END_NAMESPACE
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          MainWindow(QWidget *parent = nullptr);
          ~MainWindow();
          
             // dialog d2 needs to have a pointer to d3 so if d3 is already
             // open it can just show it.  Then d2 needs the ability to
             // inform main (as in mainwindow.h, this object) that d3 has been created.
          QDialog * get_d3_pointer();
          void      put_d3_pointer( QDialog * temp );
      
      private slots:
          void on_pb_open_d2_clicked(bool checked);
      
          void on_pb_open_d3_clicked();
      
      private:
          Ui::MainWindow *ui;
          QDialog * d2 = NULL;
          QDialog * d3 = NULL;
      };
      #endif // MAINWINDOW_H
      

      next is mainwindow.cpp

      #include "mainwindow.h"
      #include "./ui_mainwindow.h"
      #include "qdialog.h"
       
      MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      
      void MainWindow::on_pb_open_d2_clicked(bool checked)
      {
          if( d2 == NULL )
             d2 = new( QDialog );
          d2->show();
          d2->setWindowTitle( "dialog D2");
             // When dialog d2 is opened, copy the local 'this' pointer to d2 so that d2 can
             // determine if d3 has been created.
             // The next line has the message:  No member named 'set_main_dialog_pointer' in 'QDialog'
             // True, but, object d2 has that function declared.  This is to call it.
          d2->set_main_dialog_pointer( this );
      }
      
      
      void MainWindow::on_pb_open_d3_clicked()
      {
          if( d3 == NULL )
             d3 = new( QDialog );
          d3->show();
          d3->setWindowTitle( "dialog D3");
      }
      
         // cannot get the above code to work so have not completed these items.
      QDialog * MainWindow::get_d3_pointer()
      {
          return d3;
      }
      void      MainWindow::put_d3_pointer( QDialog * temp )
      {
          d3 = temp;
      }
      
      

      next is d2.h

      #ifndef D2_H
      #define D2_H
      
      #include <QDialog>
      
      namespace Ui {
      class d2;
      }
      
      class d2 : public QDialog
      {
          Q_OBJECT
      
      public:
          explicit d2(QWidget *parent = nullptr);
          ~d2();
             // The main dialog can call this function, provide its "this" pointer,
             // so this object, d2, can get the value of main's d3 pointer.
          void set_main_dialog_pointer( QDialog * temp );
      
      private slots:
          void on_pb_open_d3_2_clicked();
          QDialog * main_window_ptr = NULL;
      
      private:
          Ui::d2 *ui;
          QDialog * local_d3_ptr;
          
      };
      
      #endif // D2_H
      

      next is d2.cpp

      #include "d2.h"
      #include "ui_d2.h"
      #include "mainwindow.h"
      
      d2::d2(QWidget *parent)
          : QDialog(parent)
          , ui(new Ui::d2)
      {
          ui->setupUi(this);
      }
      
      d2::~d2()
      {
          delete ui;
      }
         // This is the second push button that can create/open dialog d3.
      void d2::on_pb_open_d3_2_clicked()
      {
             // get main's pointer to d3.  It may or may not be valid
             // The next line has the error message:
             // No member 'get_d3_pointer' in 'QDialog'
             // True, but that function is declared in mainwindow.h
             // which should be pointed to my main_window_ptr.
          local_d3_ptr = main_window_ptr->get_d3_pointer();
          if( local_d3_ptr == NULL )
          {
              local_d3_ptr = new( local_d3_ptr );
                 // next line has same errors noted a few lines up.
              main_window_ptr->put_d3_pointer( local_d3 );
          }
      }
      
      void d2::set_main_dialog_pointer( QDialog * temp )
      {
          main_window_ptr = temp;
      }
      
         // from post by Pl45m4
         // changed m_dialog to match this code with d3, the pointer to the dialog
         // to be opened.  Many errors here.  The text of the first is:
         // A type specifier is required for all declarations.
                                                       
      connect(p, &QPushButton::clicked, this, [=](){
          
          if (local_d3)
              local_d3->show();
      });
      
      

      &&&&&&&&&&&&&&&&&&&&&&&&
      files d3.h and d3.cpp have not yet been edited. The dialog has been opened from main window, but not from d2, which is the goal.

      mainwidow.ui has two pushbuttons as shown below, the upper left corner of that dialog

      main_window.png

      dialog d2 has just one added pushbutton, to open d3. It is named pb_open_d3_2

      d2_dialog.png

      files d3.h, d3.cpp, and d3.ui have not been changed after being created by Qt Creator.

      &&&&&&&&&&&&&&&&&
      Finally, to restate the goal of this app: The main dialog has the ability to open and show dialog d3. That is just standard code. The goal is to provide dialog d2 with the ability to open and/or show dialog d3.

      Pl45m4P Online
      Pl45m4P Online
      Pl45m4
      wrote on last edited by Pl45m4
      #6

      @Bryan-Kelly said in Open a dialog from other than mainwindow:

      Finally, to restate the goal of this app: The main dialog has the ability to open and show dialog d3. That is just standard code. The goal is to provide dialog d2 with the ability to open and/or show dialog d3.

      Have you looked at my code? This it exactly what it does.
      (Dialog_One = your "d2", Dialog_Two = your "d3")

      Dialogs.gif

      Edit:

      @Bryan-Kelly said in Open a dialog from other than mainwindow:

      // from post by Pl45m4
      // changed m_dialog to match this code with d3, the pointer to the dialog
      // to be opened. Many errors here. The text of the first is:
      // A type specifier is required for all declarations.

      connect(p, &QPushButton::clicked, this, [=](){
         
         if (local_d3)
             local_d3->show();
      });
      

      You can't throw pieces of code in at random.
      Maybe I haven't explained properly.

      The connection belongs in the constructor of d2 (to connect the button with the code between the curly brackets).
      (-> called C++ Lambda )
      I saved myself the effort of writing the each slot as separate function, but you can replace that with a regular function or slot.

      This, for example, can't work / produces your error respectively, because d1 and d2 are actually QDialogs (subsclasses) but only a d1 or d2 instance knows about the functions you have added.
      With the code below (where you pass the pointers around), you pass the pointer as QDialog type. Doesn't throw any error, because it's valid.
      But it makes no sense.


      Side note:
      ... unless you want to store a bunch of different subclasses from one general type in a single container:

      Say you have these classes and they all inherit from a "super" class called Super

      class A : public Super
      class B : public Super
      class C : public Super
      

      To store their pointers in one container all together, you could do something like:

      QList<Super *> container;
      

      Now back to your issue.

      Here is what you wrote:

      void d2::set_main_dialog_pointer( QDialog * temp )
      {
          main_window_ptr = temp;
      }
      

      temp and main_window_ptr are QDialog pointers from now on (in d2 class) and QDialog has no function like get_d3_pointer().
      So you get the error message as you write here

             // The next line has the error message:
             // No member 'get_d3_pointer' in 'QDialog'
             // True, but that function is declared in mainwindow.h
             // which should be pointed to my main_window_ptr.
      

      I usually don't post complete projects, because the learning effect is not that high when looking at somebody else's code. Everybody has it's own style how you would solve things etc.
      But this is the full code of the working example:

      MainWindow.h

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      
      class Dialog_One;
      class Dialog_Two;
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          MainWindow(QWidget *parent = nullptr);
          ~MainWindow();
      
      
      private:
      
          Dialog_One *m_dialogOne;
          Dialog_Two *m_dialogTwo;
      };
      #endif // MAINWINDOW_H
      

      MainWindow.cpp

      #include "mainwindow.h"
      #include <QLayout>
      #include <QPushButton>
      #include "dialog_one.h"
      #include "dialog_two.h"
      
      MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent)
          , m_dialogOne{nullptr}
          , m_dialogTwo{nullptr}
      
      {
          QWidget *w = new QWidget;
          QHBoxLayout *hbox = new QHBoxLayout(w);
          w->setLayout(hbox);
      
          QPushButton * p1 = new QPushButton("open Dialog_One", this);
          QPushButton * p2 = new QPushButton("open Dialog_Two", this);
      
          connect(p1, &QPushButton::clicked, this, [=](){
      
              if(m_dialogOne)
                  m_dialogOne->show();
              else if (m_dialogTwo)
              {
                  m_dialogOne = new Dialog_One(m_dialogTwo, this);
                  m_dialogOne->show();
              }
              else
              {
                  m_dialogTwo = new Dialog_Two(this);
                  m_dialogOne = new Dialog_One(m_dialogTwo, this);
                  m_dialogOne->show();
              }
          });
      
          connect(p2, &QPushButton::clicked, this, [=](){
      
              if(m_dialogTwo)
                  m_dialogTwo->show();
              else
              {
                  m_dialogTwo = new Dialog_Two(this);
                  m_dialogTwo->show();
              }
          });
      
          hbox->addWidget(p1);
          hbox->addWidget(p2);
          setCentralWidget(w);
      }
      
      MainWindow::~MainWindow() {}
      

      Dialog_One.h

      #ifndef DIALOG_ONE_H
      #define DIALOG_ONE_H
      
      #include <QDialog>
      #include "dialog_two.h"
      
      class Dialog_One : public QDialog
      {
         Q_OBJECT
      public:
          Dialog_One(Dialog_Two *dialog = nullptr, QWidget *parent = nullptr);
          ~Dialog_One();
      
      private:
          Dialog_Two *m_dialog;
      };
      
      #endif // DIALOG_ONE_H
      

      Dialog_One.cpp

      #include "dialog_one.h"
      #include <QPushButton>
      #include <QLayout>
      
      Dialog_One::Dialog_One(Dialog_Two *dialog, QWidget *parent)
          : QDialog{parent}
          , m_dialog{dialog}
      {
          setWindowTitle("Dialog_One");
          setObjectName("Dialog_One");
      
          QPushButton *p = new QPushButton("Show Dialog_Two", this);
      
          QHBoxLayout *hbox = new QHBoxLayout(this);
          hbox->addWidget(p);
          setLayout(hbox);
      
          connect(p, &QPushButton::clicked, this, [=](){
      
              if (m_dialog)
                  m_dialog->show();
          });
      }
      

      Dialog_Two.h, actually not modified. Just basic QDialog subclass.

      #ifndef DIALOG_TWO_H
      #define DIALOG_TWO_H
      
      #include <QDialog>
      
      class Dialog_Two : public QDialog
      {
         Q_OBJECT
      public:
          Dialog_Two(QWidget *parent = nullptr);
      };
      
      #endif // DIALOG_TWO_H
      

      Dialog_Two.cpp

      #include "dialog_two.h"
      
      Dialog_Two::Dialog_Two(QWidget *parent)
          : QDialog{parent}
      {
      }
      
      

      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

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

        in your mainwindow.h is

        Dialog_one *m_dialogOne;
        dialog_Two *m_dialogTwo;
        

        I don't know what Dialog_One and Dialog_Two are.
        I presume they represent the two dialogs I created and named d2 and d3.
        Those have already been created and are in mainwindow.h in the format

           QDialog * d2 = NULL;
           QDialog * d3 = NULL;
        

        Switch to mainwindow.cpp. The code I detect as relevant is

            QPushButton * p1 = new QPushButton("open Dialog_One", this);
            QPushButton * p2 = new QPushButton("open Dialog_Two", this);
        

        Presume also that this belongs in the constructor for main, my shorthand for mainwindow.h, .cpp, and .ui

        That seems to present a problem because as soon as the constructor completes those private pointers named p1 and p2 no longer exist. So back up to mainwindow.h and declare the pointers in there. Add the include while at it.

        That constructor now looks like this:

        MainWindow::MainWindow(QWidget *parent)
            : QMainWindow(parent)
            , ui(new Ui::MainWindow)
        {
            ui->setupUi(this);
            QPushButton * p1 = new QPushButton("open Dialog_One", this);
            QPushButton * p2 = new QPushButton("open Dialog_Two", this);
        }
        

        Next is the function:

        connect(p1, &QPushButton::clicked, this, [=]()
        { }
        

        I don't understand that. I don't know what is intended by the [=], an optional = character and maybe something else? Qt Creator does not approve of it.

        A google search provided the format:

        int connect( int socket, const struct sockaddr *address, socklen_t address_len);
        

        argument 1 is "int socket", but the first argument used is p1, a pointer, and pointers don't go into a standard int.

        argument 3 is "socklen_t address_len" and looks like the length of an address. The use of "this" does not seem to meet that need.

        This appears critical and I must stop here and request clarification.

        Meanwhile, I will be attempting to implement the code provided later in the post and see what happens. I have some events in progress at home so this may take me a couple of hours.
        Thank you for your time and patience.

        Pl45m4P 1 Reply Last reply
        0
        • B Bryan Kelly

          in your mainwindow.h is

          Dialog_one *m_dialogOne;
          dialog_Two *m_dialogTwo;
          

          I don't know what Dialog_One and Dialog_Two are.
          I presume they represent the two dialogs I created and named d2 and d3.
          Those have already been created and are in mainwindow.h in the format

             QDialog * d2 = NULL;
             QDialog * d3 = NULL;
          

          Switch to mainwindow.cpp. The code I detect as relevant is

              QPushButton * p1 = new QPushButton("open Dialog_One", this);
              QPushButton * p2 = new QPushButton("open Dialog_Two", this);
          

          Presume also that this belongs in the constructor for main, my shorthand for mainwindow.h, .cpp, and .ui

          That seems to present a problem because as soon as the constructor completes those private pointers named p1 and p2 no longer exist. So back up to mainwindow.h and declare the pointers in there. Add the include while at it.

          That constructor now looks like this:

          MainWindow::MainWindow(QWidget *parent)
              : QMainWindow(parent)
              , ui(new Ui::MainWindow)
          {
              ui->setupUi(this);
              QPushButton * p1 = new QPushButton("open Dialog_One", this);
              QPushButton * p2 = new QPushButton("open Dialog_Two", this);
          }
          

          Next is the function:

          connect(p1, &QPushButton::clicked, this, [=]()
          { }
          

          I don't understand that. I don't know what is intended by the [=], an optional = character and maybe something else? Qt Creator does not approve of it.

          A google search provided the format:

          int connect( int socket, const struct sockaddr *address, socklen_t address_len);
          

          argument 1 is "int socket", but the first argument used is p1, a pointer, and pointers don't go into a standard int.

          argument 3 is "socklen_t address_len" and looks like the length of an address. The use of "this" does not seem to meet that need.

          This appears critical and I must stop here and request clarification.

          Meanwhile, I will be attempting to implement the code provided later in the post and see what happens. I have some events in progress at home so this may take me a couple of hours.
          Thank you for your time and patience.

          Pl45m4P Online
          Pl45m4P Online
          Pl45m4
          wrote on last edited by Pl45m4
          #8

          @Bryan-Kelly said in Open a dialog from other than mainwindow:

          in your mainwindow.h is

          Dialog_one *m_dialogOne;
          dialog_Two *m_dialogTwo;

          I don't know what Dialog_One and Dialog_Two are.
          I presume they represent the two dialogs I created and named d2 and d3.
          Those have already been created and are in mainwindow.h in the format

          QDialog * d2 = NULL;
          QDialog * d3 = NULL;

          Can you spot any difference there? Among other things, this is one of the reasons why your code is condemned to fail/throw errors.

          @Pl45m4 said in Open a dialog from other than mainwindow:

          Have you looked at my code? This it exactly what it does.
          (Dialog_One = your "d2", Dialog_Two = your "d3")

          Here I've written what the Dialogs are

          @Bryan-Kelly said in Open a dialog from other than mainwindow:

          Switch to mainwindow.cpp. The code I detect as relevant is

          QPushButton * p1 = new QPushButton("open Dialog_One", this);
          QPushButton * p2 = new QPushButton("open Dialog_Two", this);
          

          This is not relevant. I created the buttons you've added with QtDesigner by code, because I don't use Designer.

          @Bryan-Kelly said in Open a dialog from other than mainwindow:

          Presume also that this belongs in the constructor for main, my shorthand for mainwindow.h, .cpp, and .ui

          You can see in my complete code example that it belongs indeed in MainWindow::MainWindow() (constructor for MainWindow).
          The main.cpp has/needs no constructor, since it's not a class.

          @Bryan-Kelly said in Open a dialog from other than mainwindow:

          That seems to present a problem because as soon as the constructor completes those private pointers named p1 and p2 no longer exist. So back up to mainwindow.h and declare the pointers in there.

          They don't need to. I've created the buttons, added them to MainWindow's centralWidget - layout, so they will be visible on the screen (as part of the main window MainWindow). Then I connected what should happen on click (via lambda connections) and that's it.
          To make this example work, you don't need any further access to them.
          And since they are now part of the QObject tree, they get deleted when their parent is (i.e. the MainWindow).

          @Bryan-Kelly said in Open a dialog from other than mainwindow:

          I don't understand that. I don't know what is intended by the [=], an optional = character and maybe something else? Qt Creator does not approve of it.

          Regarding this and the other questions,

          Please re-read my answer above, I've edited it multiple times now. Everything is explained there.

          @Bryan-Kelly said in Open a dialog from other than mainwindow:

          A google search provided the format:

          int connect( int socket, const struct sockaddr *address, socklen_t address_len);

          You probably picked the wrong page here. This doesn't look like a Qt connection.
          The connect(....) function is used in many frameworks, software/libraries.

          Here is the correct one:

          • https://doc.qt.io/qt-6/signalsandslots.html

          This section also includes a C++ lambda connection as I have used.
          (4th code snippet)

          • https://doc.qt.io/qt-6/signalsandslots.html#signals-and-slots-with-default-arguments

          If debugging is the process of removing software bugs, then programming must be the process of putting them in.

          ~E. W. Dijkstra

          1 Reply Last reply
          2
          • B Offline
            B Offline
            Bryan Kelly
            wrote on last edited by
            #9

            @Pl45m4 said in Open a dialog from other than mainwindow:

            This is not relevant. I created the buttons you've added with QtDesigner by code, because I don't use Designer.

            First, your post represents some significant changes in how I do things. I am not ignoring, just going slow. We have home renovations in progress slowing me down considerably.

            As quoted you don't use Designer. I presume that is the tool used to create dialogs with drag and drop. To my opinion that saves a lot of code needed to create and placing all the user tools. If I understand correctly, you write the code to place each tool. Is there a simple reason for doing this rather than using Designer?

            Thank you for your time and patience.

            SGaistS 1 Reply Last reply
            0
            • B Bryan Kelly

              @Pl45m4 said in Open a dialog from other than mainwindow:

              This is not relevant. I created the buttons you've added with QtDesigner by code, because I don't use Designer.

              First, your post represents some significant changes in how I do things. I am not ignoring, just going slow. We have home renovations in progress slowing me down considerably.

              As quoted you don't use Designer. I presume that is the tool used to create dialogs with drag and drop. To my opinion that saves a lot of code needed to create and placing all the user tools. If I understand correctly, you write the code to place each tool. Is there a simple reason for doing this rather than using Designer?

              Thank you for your time and patience.

              SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #10

              @Bryan-Kelly hi,

              There are several reasons:

              • less tools to use (Designer and uic)
              • all code in a single place (with Designer you have a separate file generated)
              • personally, I am faster at writing a UI than doing drag and drop with Designer

              Note that I am not against Designer, it just does not fit how I am used to code GUIs.

              From a pure forum point of view, it's less code to create a minimal reproducer.

              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
              • B Offline
                B Offline
                Bryan Kelly
                wrote on last edited by
                #11

                I apologize, but I cannot detect the answer I need in the replies provided so far, so here an an attempt at simplifying. The core question is so simple in concept, but it takes so much to set the stage to ask the question.

                Create a project with two dialogs. The first dialog is created as the initial project is created, the second dialog is added. In the main project add these lines of code:

                int main_x = 1;  // in file mainwindow.h
                ...
                int MainWindow::get_x( return main_x );  // in file mainwindow.cpp
                

                In the added dialog, create a pushbutton, and in its on_clicked() function, call that function in mainwindow.cpp.

                local_x = MainWindow->get_x();
                
                

                The problem
                I cannot find the name of the instance, (the name of the object instantiated when the app is run) such that its functions can be called from the second dialog. What replaces that word: MainWindow-> ?

                Thanks again for your time and patience.

                Pl45m4P 1 Reply Last reply
                0
                • B Bryan Kelly

                  I apologize, but I cannot detect the answer I need in the replies provided so far, so here an an attempt at simplifying. The core question is so simple in concept, but it takes so much to set the stage to ask the question.

                  Create a project with two dialogs. The first dialog is created as the initial project is created, the second dialog is added. In the main project add these lines of code:

                  int main_x = 1;  // in file mainwindow.h
                  ...
                  int MainWindow::get_x( return main_x );  // in file mainwindow.cpp
                  

                  In the added dialog, create a pushbutton, and in its on_clicked() function, call that function in mainwindow.cpp.

                  local_x = MainWindow->get_x();
                  
                  

                  The problem
                  I cannot find the name of the instance, (the name of the object instantiated when the app is run) such that its functions can be called from the second dialog. What replaces that word: MainWindow-> ?

                  Thanks again for your time and patience.

                  Pl45m4P Online
                  Pl45m4P Online
                  Pl45m4
                  wrote on last edited by Pl45m4
                  #12

                  @Bryan-Kelly said in Open a dialog from other than mainwindow:

                  The core question is so simple in concept, but it takes so much to set the stage to ask the question.

                  Create a project with two dialogs. The first dialog is created as the initial project is created, the second dialog is added. In the main project add these lines of code:

                  int main_x = 1;  // in file mainwindow.h
                  ...
                  int MainWindow::get_x( return main_x );  // in file mainwindow.cpp
                  

                  Is main_x the simplification of your dialog classes dx (d1, d2, d3 or whatever you call them)?

                  The problem
                  I cannot find the name of the instance, (the name of the object instantiated when the app is run) such that its functions can be called from the second dialog. What replaces that word: MainWindow-> ?

                  It's better to choose a "top-down" approach, than a "bottom-up". The MainWindow obviously has to know about the dialogs, and by design it makes more sense to only do what's really needed in the child dialogs. Let the parent (the MainWindow) manage/delegate the childs (the dialogs), not the other way round.

                  For your design idea to work, you would need to share the pointer to the MainWindow object with all its childs (dialogs). Then you can call the functions from there.
                  But this is not recommended.

                  To hold onto your example with the int x, even though I assume you are trying to figure out how to deal with your dialog instances:

                  There are basically two ways of retrieving a value from a dialog, using the signal&slot mechanism or using get functions.
                  But as I've said above, usually the MainWindow would call the dialog's function to retrieve some value (e.g. your int x, whose value might come from an user input) and not the dialog calls a function from it's parent to actively "get" a value.

                  Doing it the other way around is a bad design that may work, but can lead to more problems later or overcomplicate the structure of your application because then everything is tightly coupled and you have to be careful with the lifetime and deletion of almost everything to avoid crashing your app.

                  So to retrieve a value FROM a dialog, you can do something like:

                  int m_x;
                  int MyDialog::getX() const {
                  return m_x;
                  }
                  
                  {
                     MyDialog dlg;
                     dlg.show();
                     int xFromDialog = dlg.getX();
                  }
                  

                  This works for modeless dialogs and only to get a value from them.
                  To get your data into your dialog, do it as I did here:

                  @Pl45m4 said in Open a dialog from other than mainwindow:

                          m_dialogTwo = new Dialog_Two(this);
                          m_dialogOne = new Dialog_One(m_dialogTwo, this); // I passed "data" = d2 pointer to d1 
                          m_dialogOne->show();
                  

                  Pass data to it with the dialogs constructor... but don't pass the whole MainWindow.
                  Thanks to the Meta-Object system, you actually have access to every QObjects parent using parent().
                  The second parameter this makes MainWindow a direct parent of Dialog_One.
                  But this is not save to use since it might change.

                  The simplification with int would look like:
                  (re-using my dialog subclass from previous post)

                  // dialog_one.h
                  Dialog_One(int x = 0, QWidget *parent = nullptr);
                  private:
                       int m_x;
                  
                  // dialog_one.cpp
                  Dialog_One::Dialog_One(int x, QWidget *parent)
                      : QDialog{parent}
                      , m_x{x} // assign x from constructor to private int member variable
                  {
                  }
                  
                  // Usage
                  // mainwindow.cpp
                  int main_int = 42;
                  Dialog_One *myDialog = new Dialog_One(main_int, this);
                  

                  There is no need ever to pass the whole parent instance to a child.
                  Feed them the data they need to work, then wait for the "callbacks" (like Qt signals) or retrieve the data manually (call from parent) using get-functions.

                  Little modal (blocking) dialog example:

                  Assume the dialog has an input field for data like Age and you want to pass this to your MainWindow after the user clicks OK ("accepts" the dialog).

                  // dialog.h
                  int getAge() const { return m_age; }
                  
                  
                  // mainWindow.cpp
                  { // some scope
                    Dialog dlg;
                    if (dlg.exec() == QDialog::Accepted)
                    {
                        int ageFromDialog = dlg.getAge();
                        qDebug() << "The dialog contains age value: " << ageFromDialog;
                    }
                  }
                  

                  If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                  ~E. W. Dijkstra

                  B 1 Reply Last reply
                  3
                  • Pl45m4P Pl45m4

                    @Bryan-Kelly said in Open a dialog from other than mainwindow:

                    The core question is so simple in concept, but it takes so much to set the stage to ask the question.

                    Create a project with two dialogs. The first dialog is created as the initial project is created, the second dialog is added. In the main project add these lines of code:

                    int main_x = 1;  // in file mainwindow.h
                    ...
                    int MainWindow::get_x( return main_x );  // in file mainwindow.cpp
                    

                    Is main_x the simplification of your dialog classes dx (d1, d2, d3 or whatever you call them)?

                    The problem
                    I cannot find the name of the instance, (the name of the object instantiated when the app is run) such that its functions can be called from the second dialog. What replaces that word: MainWindow-> ?

                    It's better to choose a "top-down" approach, than a "bottom-up". The MainWindow obviously has to know about the dialogs, and by design it makes more sense to only do what's really needed in the child dialogs. Let the parent (the MainWindow) manage/delegate the childs (the dialogs), not the other way round.

                    For your design idea to work, you would need to share the pointer to the MainWindow object with all its childs (dialogs). Then you can call the functions from there.
                    But this is not recommended.

                    To hold onto your example with the int x, even though I assume you are trying to figure out how to deal with your dialog instances:

                    There are basically two ways of retrieving a value from a dialog, using the signal&slot mechanism or using get functions.
                    But as I've said above, usually the MainWindow would call the dialog's function to retrieve some value (e.g. your int x, whose value might come from an user input) and not the dialog calls a function from it's parent to actively "get" a value.

                    Doing it the other way around is a bad design that may work, but can lead to more problems later or overcomplicate the structure of your application because then everything is tightly coupled and you have to be careful with the lifetime and deletion of almost everything to avoid crashing your app.

                    So to retrieve a value FROM a dialog, you can do something like:

                    int m_x;
                    int MyDialog::getX() const {
                    return m_x;
                    }
                    
                    {
                       MyDialog dlg;
                       dlg.show();
                       int xFromDialog = dlg.getX();
                    }
                    

                    This works for modeless dialogs and only to get a value from them.
                    To get your data into your dialog, do it as I did here:

                    @Pl45m4 said in Open a dialog from other than mainwindow:

                            m_dialogTwo = new Dialog_Two(this);
                            m_dialogOne = new Dialog_One(m_dialogTwo, this); // I passed "data" = d2 pointer to d1 
                            m_dialogOne->show();
                    

                    Pass data to it with the dialogs constructor... but don't pass the whole MainWindow.
                    Thanks to the Meta-Object system, you actually have access to every QObjects parent using parent().
                    The second parameter this makes MainWindow a direct parent of Dialog_One.
                    But this is not save to use since it might change.

                    The simplification with int would look like:
                    (re-using my dialog subclass from previous post)

                    // dialog_one.h
                    Dialog_One(int x = 0, QWidget *parent = nullptr);
                    private:
                         int m_x;
                    
                    // dialog_one.cpp
                    Dialog_One::Dialog_One(int x, QWidget *parent)
                        : QDialog{parent}
                        , m_x{x} // assign x from constructor to private int member variable
                    {
                    }
                    
                    // Usage
                    // mainwindow.cpp
                    int main_int = 42;
                    Dialog_One *myDialog = new Dialog_One(main_int, this);
                    

                    There is no need ever to pass the whole parent instance to a child.
                    Feed them the data they need to work, then wait for the "callbacks" (like Qt signals) or retrieve the data manually (call from parent) using get-functions.

                    Little modal (blocking) dialog example:

                    Assume the dialog has an input field for data like Age and you want to pass this to your MainWindow after the user clicks OK ("accepts" the dialog).

                    // dialog.h
                    int getAge() const { return m_age; }
                    
                    
                    // mainWindow.cpp
                    { // some scope
                      Dialog dlg;
                      if (dlg.exec() == QDialog::Accepted)
                      {
                          int ageFromDialog = dlg.getAge();
                          qDebug() << "The dialog contains age value: " << ageFromDialog;
                      }
                    }
                    
                    B Offline
                    B Offline
                    Bryan Kelly
                    wrote on last edited by
                    #13

                    @Pl45m4 said in Open a dialog from other than mainwindow:

                    Is main_x the simplification of your dialog classes dx (d1, d2, d3 or whatever you call them)?

                    There may be something in the question that I don't understand, but I think: No, its just an integer declared at what I think of as the top level of my application.

                    A term. I am using "main" to indicate the code that is first created when an application is created. If I take the defaults the file names used are mainwindow.h, main.cpp, mainwindow.cpp, and mainwindow.ui. So I have been using "main" to refer to the core of the app. The core that launches and anchors everything else.

                    I will have multiple dialogs that each do some things, and some of the results of those dialogs need to get back to main. I would prefer that the dialogs be able to send such data to main rather than waiting for the user to ask for the data with a button click. Then other dialogs will need that information and should be able to fetch it rather than waiting for the user to click a button in main and send it to various dialogs.

                    Ok, so a strategy change. Create a class to serve as a repository for shared data. Call it "repo" for repository. Keep the data private. Provide public get and put functions that dialogs can access. This class will not do any processing, just serve as a repository for shared data.

                    Is this a more reasonable approach?

                    Pl45m4P 1 Reply Last reply
                    0
                    • B Bryan Kelly

                      @Pl45m4 said in Open a dialog from other than mainwindow:

                      Is main_x the simplification of your dialog classes dx (d1, d2, d3 or whatever you call them)?

                      There may be something in the question that I don't understand, but I think: No, its just an integer declared at what I think of as the top level of my application.

                      A term. I am using "main" to indicate the code that is first created when an application is created. If I take the defaults the file names used are mainwindow.h, main.cpp, mainwindow.cpp, and mainwindow.ui. So I have been using "main" to refer to the core of the app. The core that launches and anchors everything else.

                      I will have multiple dialogs that each do some things, and some of the results of those dialogs need to get back to main. I would prefer that the dialogs be able to send such data to main rather than waiting for the user to ask for the data with a button click. Then other dialogs will need that information and should be able to fetch it rather than waiting for the user to click a button in main and send it to various dialogs.

                      Ok, so a strategy change. Create a class to serve as a repository for shared data. Call it "repo" for repository. Keep the data private. Provide public get and put functions that dialogs can access. This class will not do any processing, just serve as a repository for shared data.

                      Is this a more reasonable approach?

                      Pl45m4P Online
                      Pl45m4P Online
                      Pl45m4
                      wrote on last edited by Pl45m4
                      #14

                      @Bryan-Kelly said in Open a dialog from other than mainwindow:

                      @Pl45m4 said in Open a dialog from other than mainwindow:

                      Is main_x the simplification of your dialog classes dx (d1, d2, d3 or whatever you call them)?

                      There may be something in the question that I don't understand, but I think: No, its just an integer declared at what I think of as the top level of my application.

                      Yes, I wasn't asking what main_x is ( I know/can see that), I was rather asking about its meaning in your program / for you.
                      The topic is named "Open a dialog from other than mainwindow", I made couple suggestions with full examples and code snippets, and now there's an Integer you want to pass somewhere, which I said, works the same as if you would pass any other pointer or data to your dialog.

                      A term. I am using "main" to indicate the code that is first created when an application is created. If I take the defaults the file names used are mainwindow.h, main.cpp, mainwindow.cpp, and mainwindow.ui. So I have been using "main" to refer to the core of the app. The core that launches and anchors everything else

                      As said above, it's not about why the variable is called like this. More like what are you trying to do with it and why.
                      So I was wondering if you just simplified your code for your better understanding... and went from passing a QDialog pointer to passing an int... that's why I was asking.

                      I will have multiple dialogs that each do some things, and some of the results of those dialogs need to get back to main. I would prefer that the dialogs be able to send such data to main rather than waiting for the user to ask for the data with a button click. Then other dialogs will need that information and should be able to fetch it rather than waiting for the user to click a button in main and send it to various dialogs.

                      Understood. But the data doesn't "travel" from one dialog to another or to your MainWindow by itself. There needs to be some (user inter-)action going on.
                      For example, you call the get functions from within the MainWindow.
                      How it's done and how you pass data to your dialog class, I've already explained in my post here.

                      And if you don't want the user to click any buttons, what's the point using a QDialog class, which returns a "state" whether the dialog was rejected or accepted by the user?

                      Ok, so a strategy change. Create a class to serve as a repository for shared data. Call it "repo" for repository. Keep the data private. Provide public get and put functions that dialogs can access. This class will not do any processing, just serve as a repository for shared data.

                      This sounds like a data "model". Therefore have a look at Qt's Model/View section and classes:

                      • https://doc.qt.io/qt-6/model-view-programming.html

                      Ask yourself what do you really need/want... How your dialogs (or whatever you are using to display or modify your data) should look like and how you want to manage them.
                      What kind of data you have?
                      Consider using a proper data model + the right "view" class for displaying, when you are dealing with more complex data.

                      So, please, if you don't have any questions regarding how to "Open a dialog from other than mainwindow" left, mark this topic as "solved" and create new topic(s) for your further questions.
                      Because I feel like this topic isn't going somewhere. You reply to suggestions dealing with your initial problem with new/other issues.


                      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                      ~E. W. Dijkstra

                      1 Reply Last reply
                      0
                      • B Bryan Kelly has marked this topic as solved on

                      • Login

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