how can QDialog update MainWindow?



  • I have a QDialog (MemberSearch) that takes a member name and try to find it a database. If successful, I want the MainWindow to show the member's info.

    I get the following error:

    error: 'class Ui::MemberSearch' has no member named 'stackedWidget_2'
    ui->stackedWidget_2->setCurrentIndex(2);

    stackedWidget_2 is part of mainwindow. How can I access mainwindow widgets from QDialog?



  • I guess good way would be emiting singnal which triggers some kind of updating function-slot in MainWindow.
    You can as well try getting parent widget ( http://doc.qt.io/qt-5/qwidget.html#parentWidget ) however i think it is not a "clean" solution.


  • Qt Champions 2016

    Hi
    The UI is private to the class owning it.
    This means that outside class like a dialog cannot just talk to another class UI objects.
    This concept is call incapsulation
    https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)

    Very fast it means that is not a good idea that all the rest of the program knows what kind of widgets
    another class has as then if u change something, you will have to change all other places in the program that
    knew u had such widget.
    So a much better way is to use signals and slot.
    A signal is just a notification and the slot/who get the signal dont really care who send it and in this way
    we suddenly have a much better design.

    So in your case.
    You would define a new signal
    void MemberFound( MemeberInfo Info );
    in the dialog.

    and in mainwindow, hook up the signal to a slot in mainwindow
    via the connect statement.

    and then in dialog when u find the member
    u do
    emit MemberFound(theinfofound)

    and in the slot in mainwindow, you will do what ever u need when member found.

    So general rule is that if u have the need to do stuff with other class widget, you will use signals or a
    public function in that class to do what u need. You cannot and should not ever be able to say
    otherclass->ui->somewidget.



  • @mrjj, @michelson

    Here is what I did so far:

    in MemberSearch.h (QDialog), I added:

    signals:
       void MemberFound(std::string fullName);
    

    in MemberSearch.cpp (QDialog), I added the following line after the code that finds the member's info:

    emit MemberFound(rcd->getFullName());
    close();
    

    in mainwindow.h, I added:

    private slots:
       void displayMemberInfo(std::string fullName);
    

    in mainwindow.cpp, I added:

    void MainWindow::displayMemberInfo(std::string fullName)
    {
        ui->stackedWidget_2->setCurrentIndex(2);
        ui->displayFullNameLbl->setText(QString::fromStdString(fullName));
    }
    

    and inside mainwindow's constructor I added:

         MemberSearch found;
         connect(&found, SIGNAL(MemberFound(std::string)), this, SLOT(displayMemberInfo(std::string)));
    

    The app compiles and runs but the code inside

    void MainWindow::displayMemberInfo(std::string fullName)
    

    doesn't seem to execute.

    The QDialog (MemberSearch) closes, so I assume the the signal was emitted. Also, is the signal just a declaration in the .h file? Does it need an implementation in the .cpp file?

    I added qDebug() statements to both the code inside MemberSearch and mainwindow.

    inside MemberSearch:

                qDebug()<< "************About to emit signal************";
                emit MemberFound(memberRecord->getFullName()); 
                close();
    

    inside mainwindow:

        qDebug()<<"************Inside displayMemberInfo************";
        ui->stackedWidget_2->setCurrentIndex(2);
        ui->displayFullNameLbl->setText(QString::fromStdString(fullName));
    

    Only

    ************About to emit signal************
    

    prints out. What am I doing missing?


  • Qt Champions 2016

    @WhatIf said:

    and inside mainwindow's constructor I added:

     MemberSearch found;
    

    Hi
    if you add that in constructor , do you also call
    found.exec() ?

    Else it means that the found variable runs out of scope and gets deleted.

    Do you see your MemberSearch dialog at all?

    else the code looks good and clean.

    You should add
    qDebug() << "con:" << connect(&found, SIGNAL(MemberFound(std::string)), this, SLOT(displayMemberInfo(std::string)));

    to see if it returns true.

    but i dont expect MemberSearch found; to live in ctor of mainwindow.
    More like there is a button and when pressed it would
    MemberSearch found;
    found.exec();



  • if you add that in constructor , do you also call found.exec() ?

    No but after your comment I added it. What happened is when I first start the app, the QDialog show up only after I close the QDialog, mainwindow displays.

    qDebug() << "con:" << connect(&found, SIGNAL(MemberFound(std::string)), this, SLOT(displayMemberInfo(std::string)));

    I added it and it printed con: true

    Does the connect statement have to be in the constructor? All the examples I found online have the connect statement inside mainwindow constructor.

    For my app, created using Qt Designer, it has mainwindow which contains a button (member search button). Once the member search button is clicked the QDialog displays which asks for user name.

    Code inside member search button which is part of mainwindow :

    MemberSearch memSearch;
    memSearch.setModal(true);
    memSearch.setWindowFlags(Qt::CustomizeWindowHint); 
    memSearch.setWindowFlags(Qt::FramelessWindowHint); 
    memSearch.exec();
    

    Can I have the connect statement before the last line, memSearch.exec();?



  • Look, the way I see it is that you may connect something (dialog) which just is not there anymore, I'd try something like:

    //------------YourDialog.h-------------
    singals:
        void update_triggered(std::string updated_string);
    slots:
       void on_updateButton_clicked();
    
    //-------YourDialog.cpp--------
    // somwhere in constructor
    connect(ui->updateButton, SIGNAL(clicked()), this, SLOT(on_updateButton_clicked()));  
    
    void YourDialog::on_updateButton_clicked() 
    {
        //get things you want eg. process/get string you want to display @ mainwindow
        emit update_triggered("I AM UPDATED RIGHT?!");
    
    //-------mainwindow.h-------
    slots:
        void on_update_triggered(std::string str);
    
    //-----mainwindow.cpp-----
    YourDialog* dialog = new YourDialog(this);
    connect(dialog, SIGNAL(update_triggered(std::string)), this, SLOT(on_update_triggered(std::string)));
    dialog.exec();
    delete dialog;
    

  • Qt Champions 2016

    @WhatIf said:

    MemberSearch memSearch;
    ..
    MemberSearch found;

    Yes you should have connect there.
    The " MemberSearch found;" you connect in constructor don't survive.

    Here you you use another one. so that is also the reason it doesn't work for you.
    This one that you show- have no connect.
    so connect here and remove the other one from constructor.

    --

    • No but after your comment I added it. What happened is when I first start the app, the QDialog show up only after I close the QDialog, mainwindow displays.

    That is why i wondered why you had in constructor.
    the exec() calls starts a local event loop and stay in there, meaning it won't execute next statement before you
    close the dialog, So mainwindow first show when u close dialog,


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.