0

I met some problem when using Qt window and set window modality to WindowModal, really appreciate if someone can help me solving this problem

I have a window called A, it's parent of 3 windows B1, B2, and B3 (they are same class and generated in order). What I expect is that any of these three windows will block A, but they won't block each other.

According to the document, I can do this by setting B1, B2, and B3 to Qt::WindowModal. http://developer.qt.nokia.com/doc/qt-4.8/qt.html#WindowModality-enum

However, the result is that All of B1, B2, B3 will block A, which is fine, but B1 is blocked by B2, and B2 is blocked by B3, which is not as what I expect. It becomes an order (A < B1 < B2 < B3).

Anyone can tell me where's the problem ? Did I use the wrong modality? However, there're only 3 modality, and other two doesn't look like what I need.

Claire Huang
  • 961
  • 1
  • 18
  • 30
  • Can you show any code? Are you sure you didn't parent B3 -> B2 -> B1 -> A ? – jdi Feb 22 '12 at 01:13
  • 1
    Wild gues, but probably Qt::WindowModal makes modal to Parent window and all it's children. That is why it works like it works... – Kamil Klimek Feb 25 '12 at 18:44
  • Hi! My answer solve your problem? If so check as "correct", if not tell me what is missing. – Protomen Apr 12 '15 at 15:06

1 Answers1

0

I tested on a "windows7", follows the code:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dialog.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    Dialog *m1 = new Dialog(this);
    Dialog *m2 = new Dialog(this);
    Dialog *m3 = new Dialog(this);

    m1->setWindowModality(Qt::WindowModal);
    m1->setWindowTitle(tr("Window 1"));

    m2->setWindowModality(Qt::WindowModal);
    m2->setWindowTitle(tr("Window 2"));

    m3->setWindowModality(Qt::WindowModal);
    m3->setWindowTitle(tr("Window 3"));

    m1->show();
    m2->show();
    m3->show();
}

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

The only window that can be clicked is the Dialog * m3, the other is blocked, but when you click MainWindow you may notice that the effect is different.

If you click the Dialog * m1 or Dialog * m2 to Dialog * m3 window does not BLINK (effect blink), but if I click MainWindow to Dialog * m3 window will BLINK (effect blink).

That is the type modal windows do not block because it is waiting for a response,

ie to call it:

    Dialog *m1 = new Dialog(this);
    Dialog *m2 = new Dialog(this);
    Dialog *m3 = new Dialog(this);

I'll have to confirm the response one at a time, because it works in a synchronized and not asynchronized mode, in other words, the type Modal windows are intended to send a request to the parent window, so how much you do not complete the request all cascade windows are blocked. In other words, windows modal (with "parent" setted), will always expect an response (like the "exec").

Alternative solution:

You can create a lock for "MainWindow window" using setEnable (false) and when all dialogs are closed to "MainWindow window" is enabled with setEnable (true). See example:

note: if you will use a modal window to submit responses to the parent window, in this example you need to use the SLOTS: accept(), reject() or finished(int)

mainwindow.h

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;

public slots:
    void showChilds();
    void findDialogs(const int a = -1);
};

mainwindow.cpp

#include "dialog.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QTimer>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(showChilds()));
}

void MainWindow::showChilds() {
    setEnabled(false);

    Dialog *m1 = new Dialog(this);
    Dialog *m2 = new Dialog(this);
    Dialog *m3 = new Dialog(this);

    m1->setAttribute(Qt::WA_DeleteOnClose, true);
    m2->setAttribute(Qt::WA_DeleteOnClose, true);
    m3->setAttribute(Qt::WA_DeleteOnClose, true);

    m1->setWindowTitle("1");
    m2->setWindowTitle("2");
    m3->setWindowTitle("3");

    m1->show();
    m2->show();
    m3->show();

    QObject::connect(m1, SIGNAL(finished(int)), this, SLOT(findDialogs(int)));
    QObject::connect(m2, SIGNAL(finished(int)), this, SLOT(findDialogs(int)));
    QObject::connect(m3, SIGNAL(finished(int)), this, SLOT(findDialogs(int)));
}

void MainWindow::findDialogs(const int a)
{
    if(a==-1){
        QObject *tmp;
        QObjectList list = this->children();
        const int j = list.length();
        for(int i=0; i < j; i++) {
            tmp = (QObject *) (list.at(i));
            if(tmp!=0 && tmp->objectName()=="Dialog") {
                return;
            }
        }

        setEnabled(true);
    } else {
        QTimer::singleShot(1, this, SLOT(findDialogs()));
    }
}
Protomen
  • 9,471
  • 9
  • 57
  • 124