How to make a modal dialog stay on top of an existing modal dialog?
-
Hi,
I need to create a modal dialog on top of another modal dialog. Following code shows how I am creating the dialogs.MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { auto mainWidget = new QWidget(this); auto button = new QPushButton("Click", mainWidget); QVBoxLayout* layout = new QVBoxLayout; layout->addWidget(button, Qt::AlignCenter); mainWidget->setLayout(layout); setCentralWidget(mainWidget); connect(button, SIGNAL(clicked()), this, SLOT(buttonClick())); } void MainWindow::buttonClick1() { m_dialog2 = new QDialog(m_dialog1); m_dialog2->exec(); } void MainWindow::buttonClick() { m_dialog1 = new QDialog(this); auto layout = new QVBoxLayout; auto button = new QPushButton("Click", m_dialog1); connect(button, SIGNAL(clicked()), this, SLOT(buttonClick1())); layout->addWidget(button); m_dialog1->setLayout(layout); m_dialog1->exec(); }
The problem is that the second dialog (m_dialog2) is modal with respect to the main window, but loses focus and moves to the background if the first dialog is clicked (m_dialog1). Although the first dialog accepts focus, it doesn't accept any click events, which makes it feel like the app is frozen.
How can I make the second dialog modal with respect to the first dialog as well?Thanks!
EDIT: I am testing this on MacOS 10.14.6/Qt 5.12.4.
-
Hi,
AFAIK, you did set the modality correctly however you are chaining blocking event loops when calling exec and IIRC, you can have issues with that. I would recommend moving to the use of QDialog::open which changes how you handle the dialog slightly but avoids nested event loops.
-
@SGaist Unfortunately I am working on a legacy codebase, so I would like to avoid changing the
QDialog::exec
calls toQDialog::open
(to avoid code restructuring at this point).Though I did change
exec
toopen
in the sample code that I shared. It does work but converts both the dialogs to sheets even though I am not specifyingQt::Sheet
window flag. In fact, if I explicitly remove theQt::Sheet
window flag from the dialog (after callingopen
), it disappears/closes.I also tried changing the window modality to
Qt::WindowModal
while usingexec
, but it also presents the dialogs as sheets. -
@SGaist Unfortunately I am working on a legacy codebase, so I would like to avoid changing the
QDialog::exec
calls toQDialog::open
(to avoid code restructuring at this point).Though I did change
exec
toopen
in the sample code that I shared. It does work but converts both the dialogs to sheets even though I am not specifyingQt::Sheet
window flag. In fact, if I explicitly remove theQt::Sheet
window flag from the dialog (after callingopen
), it disappears/closes.I also tried changing the window modality to
Qt::WindowModal
while usingexec
, but it also presents the dialogs as sheets.The problem is that the second dialog (m_dialog2) is modal with respect to the main window, but loses focus and moves to the background if the first dialog is clicked (m_dialog1).
Does it? It doesn't help that you didn't think it relevant to state what platform you are on. I am Qt 5.12.2 under Ubuntu 19.04, GNOME desktop. All works as expected.
m_dialog1
is modal wrtMainWindow
,m_dialog2
is modal wrtm_dialog1
(not sure what you meant by your "The problem is that the second dialog (m_dialog2) is modal with respect to the main window,", it isn't, unless you mean "indirectly" via grand-parentage), and in all cases the correct dialog remains up-front and no back-dalog can be clicked/focussed while it's there.....I believe, but admit I am not sure, that in the past I had an application which did this under Windows too, and the behaviour was the same as under Linux, with the modal hierarchy being perfectly respected.
Furthermore, the default for[EDIT incorrect, as per @schrute reply below], so settingQDialog::exec()
is alreadyQt::WindowModal
for a dialog with a parentm_dialog[12]->setWindowModality(Qt::WindowModal)
had no different effect, and I did not get any "but it also presents the dialogs as sheets". Nor did I find changingexec()
toopen()
caused any "sheet-ness". -
The problem is that the second dialog (m_dialog2) is modal with respect to the main window, but loses focus and moves to the background if the first dialog is clicked (m_dialog1).
Does it? It doesn't help that you didn't think it relevant to state what platform you are on. I am Qt 5.12.2 under Ubuntu 19.04, GNOME desktop. All works as expected.
m_dialog1
is modal wrtMainWindow
,m_dialog2
is modal wrtm_dialog1
(not sure what you meant by your "The problem is that the second dialog (m_dialog2) is modal with respect to the main window,", it isn't, unless you mean "indirectly" via grand-parentage), and in all cases the correct dialog remains up-front and no back-dalog can be clicked/focussed while it's there.....I believe, but admit I am not sure, that in the past I had an application which did this under Windows too, and the behaviour was the same as under Linux, with the modal hierarchy being perfectly respected.
Furthermore, the default for[EDIT incorrect, as per @schrute reply below], so settingQDialog::exec()
is alreadyQt::WindowModal
for a dialog with a parentm_dialog[12]->setWindowModality(Qt::WindowModal)
had no different effect, and I did not get any "but it also presents the dialogs as sheets". Nor did I find changingexec()
toopen()
caused any "sheet-ness".It doesn't help that you didn't think it relevant to state what platform you are on.
I am testing this on MacOS 10.14.6 with Qt 5.12.4.
Furthermore, the default for QDialog::exec() is already Qt::WindowModal for a dialog with a parent
As per the documentation, by default the dialog is
Qt::ApplicationModal
. -
It doesn't help that you didn't think it relevant to state what platform you are on.
I am testing this on MacOS 10.14.6 with Qt 5.12.4.
Furthermore, the default for QDialog::exec() is already Qt::WindowModal for a dialog with a parent
As per the documentation, by default the dialog is
Qt::ApplicationModal
.@schrute said in How to make a modal dialog stay on top of an existing modal dialog?:
I am testing this on MacOS 10.14.6 with Qt 5.12.4.
Maybe that is the difference in behaviour, I cannot say.
As per the documentation, by default, the dialog is Qt::ApplicationModal.
Damn, you are right! I could have sworn that the default was application modal when
parent = nullptr
but window modal whenparent = something
.... So for aQDialog
the relevance of parent is justbut if it has a parent, its default location is centered on top of the parent
Right?