Qt: How to give focus to a modeless QDialog create

2020-03-26 04:44发布

问题:

In my Qt Application I'm facing the following scenario: When a specific event is raised I show a modeless QDialog which asks the user for a confirmation. The Dialog is showed using show() function from a QMainWindow. Anytime the event is raised and no other modal QDialog are shown, the user is able to click the confirmation button. Unfortunately if a modal QDialog is visible when the event is raised, the modeless QDialog is unaccessible. This means that the user cannot click the confirmation button. The following code is a simplified version that causes the same problem In this example the QMainWindow contains a button, when the button is clicked a modal QDialog is shown using the exec() function in the meanwhile a QTimer has been started. Anytime I close the modal QDialog before the QTimer is elapsed the modeless dialog is accesible. If I wait until the modeless dialog is shown without closing the modal one, the modeless dialog is inaccessible (I need to close the modal one first).

MainWindows code:

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

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_pModeless = new DialogModal(this);
    connect(&m_qTimer,SIGNAL(timeout()),this,SLOT(TimerElapsed()));

}

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

void MainWindow::TimerElapsed()
{
    m_qTimer.stop();
    m_pModeless->show();
    m_pModeless->activateWindow();
    m_pModeless->raise();
    m_pModeless->setFocus();
}

void MainWindow::on_pbStartTest_clicked()
{
    m_qTimer.start(10000);
    DialogModal d(this);
    d.exec();
}

MainWindow Header:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimer>
#include "dialogmodal.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    QTimer m_qTimer;
    DialogModal *m_pModeless;
private:
    Ui::MainWindow *ui;
private slots:
    void TimerElapsed();
    void on_pbStartTest_clicked();
};

#endif // MAINWINDOW_H

DialogModal Header:

#ifndef DIALOGMODAL_H
#define DIALOGMODAL_H

#include <QDialog>

namespace Ui {
class DialogModal;
}

class DialogModal : public QDialog
{
    Q_OBJECT

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

private slots:
    void on_pbExit_clicked();

private:
    Ui::DialogModal *ui;
};

#endif // DIALOGMODAL_H

DialogModal source:

#include "dialogmodal.h"
#include "ui_dialogmodal.h"

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

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

void DialogModal::on_pbExit_clicked()
{
    close();
}

Is there anyway to give focus to the modeless dialog even when one or more modal dialog are present?

回答1:

I found a working solution:

void MainWindow::TimerElapsed()
{
    QWidget *pwidget=NULL;
    m_qTimer.stop();
    foreach(pwidget,QApplication::topLevelWidgets())
    {
        if ((pwidget->isWindow())&&(pwidget->isModal()))
        {
            m_pModeless->setParent(pwidget);
        }
    }
    if (pwidget==NULL)
    {
        m_pModeless->setParent(this);
    }
    m_pModeless->show();
    m_pModeless->activateWindow();
    m_pModeless->raise();
    m_pModeless->setFocus();
}


回答2:

When modal dialog to be activated (about to show) you may try change parent of modeless dialog to this modal dialog. As modeless dialog will have the modal dialog as parent then there is a chance to have it on top. Still it may also depend on platform.

Of course ideally to avoid such situations