想讓一個Widget成為模態,我們只需要對其設置setAttribute(Qt::WA_ShowModal, true);


想讓一個Widget成為模態,我們只需要對其設置:

setAttribute(Qt::WA_ShowModal, true);

注意:這是QWidget的成員函數 ,也就是說,QWidget可以顯示為模態或非模態!

setWindowModality

除了直接調用setAttribute外,QWidget 提供了一個易用的函數,來設置窗體的模態。其源碼如下:

void QWidget::setWindowModality(Qt::WindowModality windowModality)
{
    data->window_modality = windowModality;
    // setModal_sys() will be called by setAttribute()
    setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
    setAttribute(Qt::WA_SetWindowModality, true);
}

注意:該函數的參數取值:NonModal、WindowModal、ApplicationModal 分別對應默認情況下的

  • QDialog::show()
  • QDialog::open()
  • QDialog::exec()

如果你沒有使用QDialog::open()的需求,你可能也不需要該函數。

setModal

除了QWidget提供的成員,QDialog 提供了 setModal 的成員函數,我們看看其代碼:

void QDialog::setModal(bool modal)
{
    setAttribute(Qt::WA_ShowModal, modal);
}

不用解釋了吧?我們要顯示模態對話框,只需要類似下面的代碼:

QDialog * dlg = new QDialog();
dlg->setAttribute(Qt::WA_ShowModal, true);
dlg->show();

exec()

有問題是不?為啥exec() 直接可以顯示模態對話框呢?看QDialog源代碼吧

int QDialog::exec()
{
    Q_D(QDialog);
...
    setAttribute(Qt::WA_ShowModal, true);
...
    show();
...
    QEventLoop eventLoop;
    (void) eventLoop.exec(QEventLoop::DialogExec);
...
}

看到答案沒:exec() 先設置modal屬性,而后調用 show() 顯示對話框,最后啟用事件循環

事件循環

Qt 程序時事件驅動的,每個程序,我們需要調用 QApplication::exec() 來啟用事件循環。

int QCoreApplication::exec()
{
...
    QEventLoop eventLoop;
    int returnCode = eventLoop.exec();
...
    return returnCode;
}

用前面的 QDialog::exec() 一樣,都是調用的 QEventLoop::exec()

int QEventLoop::exec(ProcessEventsFlags flags)
{
    Q_D(QEventLoop);
...
    while (!d->exit)
        processEvents(flags | WaitForMoreEvents | EventLoopExec);
...
    return d->returnCode;
}

bool QEventLoop::processEvents(ProcessEventsFlags flags)
{
    Q_D(QEventLoop);
    if (!d->threadData->eventDispatcher)
        return false;
    if (flags & DeferredDeletion)
        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
    return d->threadData->eventDispatcher->processEvents(flags);
}

 

進一步:這將調用平台相關的函數,比如在windows下

bool QGuiEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
{
    if (!QEventDispatcherWin32::processEvents(flags))
        return false;
    if (configRequests)                        // any pending configs?
        qWinProcessConfigRequests();
    return true;
}

事件循環和線程沒有必然的聯系,事件循環可以用在QThread中,而且從Qt4.4開始,QThread的run函數默認就調用了自己的事件循環。

對與QDialog來說,當它自己的QEventLoop啟用時,主程序的 QEventLoop 當然是處於暫停狀態了。說到底,就是兩個死循環,一個在內,一個在外,只有里面的退出后,外邊的循環才會執行。不過由於兩個循環執行的命令是基本一樣的,都是調用並處理程序收到的各種事件,所以,可能變得不容易理解

 

http://doc.qt.io/qt-4.8/qwidget.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM