Hide and show UI's



  • Hello Folks,

    I have a question.

    I have 3 UI's. My requirement is any one UI should be visible at any point of time. I have push buttons on each UI's.

    My navigation between UI's are like below:

    Intially show first UI. On click of push button, first UI is hide and second UI is show --> This works
    On click of push button in second UI, second UI is hide and third UI is show --> This works
    On click of push button in third UI, third UI is hide and second UI is show and immediately entire application crashes with below warning.

    QDialog::exec: Recursive call detected

    FYI: In the second UI along with push button, I also have a list widget. For the first time when second UI was shown, list shall get populate with some data. During the navigation from third UI to second UI, I should be able to view the same hidden second UI.

    Please provide you help.

    Thanks
    Mohan



  • Take a look at [[doc:QStackedWidget]] . I hope, this will make your implementation a lot easier.



  • I don't want to implement similar to QTabWidget.

    My requirement would be like each UI should be shown as different independent windows.



  • First of all, [[doc:QStackedWidget]] is no way similar to tab widget (Atleast in appearance). Its a good idea, that you see the examples , to see what really a StackedWidget is,if you haven't gone through already.

    Now, any qwidget, you can "show":http://qt-project.org/doc/qt-4.8/qwidget.html#show or "hide":http://qt-project.org/doc/qt-4.8/qwidget.html#hide, if you want to do it separately.


  • Moderators

    It sounds like you are showing dialogs by calling exec() on them. This eventually causes that you call exec inside exec inside exec...
    Instead try to create all three windows and show()/hide() them in the same event loop. Something similar to this:
    @#include <QApplication>
    #include <QPushButton>

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    QPushButton pb1("Window 1");
    QPushButton pb2("Window 2");
    
    QObject::connect(&pb1, SIGNAL(clicked()), &pb1, SLOT(hide()));
    QObject::connect(&pb1, SIGNAL(clicked()), &pb2, SLOT(show()));
    
    QObject::connect(&pb2, SIGNAL(clicked()), &pb2, SLOT(hide()));
    QObject::connect(&pb2, SIGNAL(clicked()), &pb1, SLOT(show()));
    
    pb1.show();
    
    return a.exec(&#41;;
    

    }@



  • Hello Krzyszt,

    I tried your suggestion but din't work out.

    As I told I have 3 GUI's

    In first GUI window, on click of push button, progress bar pops up. Once progress bar completes with 100%, I shall hide first GUI window and then show second GUI.

    Second GUI window has a list widget(list items were captured during progress bar in first GUI window).
    On click of list item, I shall hide second GUI and then show third GUI.

    In third GUI when I click close button, I call close() to close third GUI and subsequently after this close operation I shall show second GUI. Unfortunately second GUI window pops and immediately entire application quits by showing "QDialog::exec: Recursive call detected"

    Thanks,
    Mohan



  • got the answer from below link:

    I should write below line in main function.

    app.setQuitOnLastWindowClosed(false);

    http://stackoverflow.com/questions/5116459/problem-with-hidden-qmainwindow-application-crashes-after-qmessagebox-is-displa



  • Try this... Hope this Example will be useful for you...

    FirstDialog.h
    @#ifndef FIRSTDIALOG_H
    #define FIRSTDIALOG_H

    #include "qthideandshowdialog.h"

    namespace Ui {
    class FirstDialog;
    }

    class FirstDialog : public QtHideAndShowDialog
    {
    Q_OBJECT

    public:
    explicit FirstDialog(QWidget *parent = 0);
    ~FirstDialog();

    private slots:
    void on_pushButton_clicked();

    private:
    Ui::FirstDialog *ui;
    };

    #endif // FIRSTDIALOG_H@

    FirstDialog.cpp
    @
    #include "seconddialog.h"
    #include "firstdialog.h"
    #include "ui_firstdialog.h"

    FirstDialog::FirstDialog(QWidget *parent) :
    QtHideAndShowDialog(parent),
    ui(new Ui::FirstDialog)
    {
    ui->setupUi(this);
    }

    FirstDialog::~FirstDialog()
    {
    delete ui;
    }

    void FirstDialog::on_pushButton_clicked()
    {
    SecondDialog d;
    this->ShowChild(&d);
    }@

    SecondDialog.h

    @#ifndef SECONDDIALOG_H
    #define SECONDDIALOG_H

    #include "qthideandshowdialog.h"

    namespace Ui {
    class SecondDialog;
    }

    class SecondDialog : public QtHideAndShowDialog
    {
    Q_OBJECT

    public:
    explicit SecondDialog(QWidget *parent = 0);
    ~SecondDialog();

    private slots:
    void on_button_goto_third_clicked();

    void on_button_back_to_first_clicked();

    private:
    Ui::SecondDialog *ui;
    };

    #endif // SECONDDIALOG_H@

    SecondDialog.cpp

    @#include <cassert>
    #include "seconddialog.h"
    #include "ui_seconddialog.h"
    #include "thirddialog.h"

    SecondDialog::SecondDialog(QWidget *parent) :
    QtHideAndShowDialog(parent),
    ui(new Ui::SecondDialog)
    {
    ui->setupUi(this);
    }

    SecondDialog::~SecondDialog()
    {
    delete ui;
    }

    void SecondDialog::on_button_back_to_first_clicked()
    {
    close();
    }

    void SecondDialog::on_button_goto_third_clicked()
    {
    ThirdDialog d;
    this->ShowChild(&d);
    if (d.m_back_to_which_dialog == 1)
    {
    this->close();
    }
    }@

    ThirdDialog.h

    @#ifndef THIRDDIALOG_H
    #define THIRDDIALOG_H

    #include "qthideandshowdialog.h"

    namespace Ui {
    class ThirdDialog;
    }

    class ThirdDialog : public QtHideAndShowDialog
    {
    Q_OBJECT

    public:
    explicit ThirdDialog(QWidget *parent = 0);
    ~ThirdDialog();

    int m_back_to_which_dialog;
    

    private slots:
    void on_button_back_to_first_clicked();

    void on_button_back_to_second_clicked();
    

    private:
    Ui::ThirdDialog *ui;
    };

    #endif // THIRDDIALOG_H@

    ThirdDialog.cpp

    @#include "thirddialog.h"
    #include "ui_thirddialog.h"

    ThirdDialog::ThirdDialog(QWidget *parent) :
    QtHideAndShowDialog(parent),
    m_back_to_which_dialog(2), //When user closes the dialog, go back to the previous/second dialog
    ui(new Ui::ThirdDialog)
    {
    ui->setupUi(this);
    }

    ThirdDialog::~ThirdDialog()
    {
    delete ui;
    }

    void ThirdDialog::on_button_back_to_first_clicked()
    {
    m_back_to_which_dialog = 1;
    close();
    }

    void ThirdDialog::on_button_back_to_second_clicked()
    {
    m_back_to_which_dialog = 2;
    close();
    }@

    QtHideandShowDialog.h

    @#ifndef QTHIDEANDSHOWDIALOG_H
    #define QTHIDEANDSHOWDIALOG_H

    #include <QDialog>

    class QtHideAndShowDialog : public QDialog
    {
    Q_OBJECT

    public:
    explicit QtHideAndShowDialog(QWidget *parent = 0);

    ///Virtual destructor as this is a base class
    virtual ~QtHideAndShowDialog() {}

    ///Show a child
    void ShowChild(QtHideAndShowDialog * const dialog);

    protected:
    ///Shows a child until it emits a close_me signal
    bool m_show_child;

    ///closeEvent that emits the close_me signal
    void closeEvent(QCloseEvent *);

    signals:
    ///Emit the closeEvent of this dialog
    void close_me();

    protected slots:
    ///Slot that needs to be called when a child signals close_me
    void close_child();

    };

    #endif // QTHIDEANDSHOWDIALOG_H@

    QtHideandShowDialog.cpp

    @#include <cassert>
    #include "qthideandshowdialog.h"

    QtHideAndShowDialog::QtHideAndShowDialog(QWidget *parent)
    : QDialog(parent),
    m_show_child(false)
    {

    }

    void QtHideAndShowDialog::close_child()
    {
    m_show_child = false;
    }

    void QtHideAndShowDialog::closeEvent(QCloseEvent *)
    {
    emit close_me();
    }

    void QtHideAndShowDialog::ShowChild(QtHideAndShowDialog * const dialog)
    {
    assert(dialog);
    this->hide();
    QObject::connect(dialog,SIGNAL(close_me()),this,SLOT(close_child()));
    m_show_child = true;
    while (m_show_child)
    {
    dialog->exec();
    }
    this->show();
    }

    @


  • Moderators

    I think you complicate things too much.
    I used two widgets in my example to be brief, but the idea is the same.

    You should be careful when using setQuitOnLastWindowClosed(false), because your app won't close now when you close the last window and will dangle in memory. To terminate you will have to call app.quit() or app.exit(code). You would have to call it in the close event of all the windows with some conditions.

    This pattern doesn't have these drawbacks. When you press the "x" in any window the app will close properly:

    @#include <QApplication>
    #include <QPushButton>
    #include <QListWidget>
    #include <QStringList>

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    QPushButton pb1("First window.\nI'll skip progress bar but you can do it the same way");
    QListWidget lw2;
    QPushButton pb3("Dialog with close button");
    
    lw2.addItems(QStringList() << "item1" << "item2" << "item3");
    
    QObject::connect(&pb1, SIGNAL(clicked()), &pb1, SLOT(hide()));
    QObject::connect(&pb1, SIGNAL(clicked()), &lw2, SLOT(show()));
    
    QObject::connect(&lw2, SIGNAL(itemClicked(QListWidgetItem*)), &lw2, SLOT(hide()));
    QObject::connect(&lw2, SIGNAL(itemClicked(QListWidgetItem*)), &pb3, SLOT(show()));
    
    QObject::connect(&pb3, SIGNAL(clicked()), &pb3, SLOT(hide()));
    QObject::connect(&pb3, SIGNAL(clicked()), &lw2, SLOT(show()));
    
    pb1.show();
    
    return a.exec&#40;&#41;;
    

    }@



  • Cool....



  • Hello Krzyszt,
    Yes you are right.
    To close windows I am using qApp->closeallwindows()



  • Hey i also have the same problem, and none of the sollutions above have worked for me so far i need to hide a form(form2) before i exec() a new dialog(form 3), and immediately after exec returns on close of that dialog(form 3), i call this->show on the form 2. But the form 2 never shows and i get the form 1 on closing form 3. i hv also noticed that replacing exec() calls to form 2 and 3 by show() and creating the child dialogs on the heap , does not hide form 1 and 2 respectively when form 2 n 3 shows , they stay visible though... Please please let me know if anybody knows what i am missing. below is a part of the code method 1 (this returns to form 1 on closing form 3 with close())

    form3 f3;
    this->hide();
    f3.exec();
    this->show();

    method 2 (this never hides from 2 but returns to form 2 on closing form3 with close())

    f3=new Menu(this);
    this->hide();
    f3->show();
    this->show();



  • Hey i also have the same problem, and none of the sollutions above have worked for me so far i need to hide a form(form2) before i exec() a new dialog(form 3), and immediately after exec returns on close of that dialog(form 3), i call this->show on the form 2. But the form 2 never shows and i get the form 1 on closing form 3. i hv also noticed that replacing exec() calls to form 2 and 3 by show() and creating the child dialogs on the heap , does not hide form 1 and 2 respectively when form 2 n 3 shows , they stay visible though... Please please let me know if anybody knows what i am missing. below is a part of the code method 1 (this returns to form 1 on closing form 3 with close())

    form3 f3;
    this->hide();
    f3.exec();
    this->show();

    method 2 (this never hides from 2 but returns to form 2 on closing form3 with close())

    f3=new Menu(this);
    this->hide();
    f3->show();
    this->show();


Log in to reply
 

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