zoukankan      html  css  js  c++  java
  • 想让一个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

  • 相关阅读:
    2019.6.20刷题统计
    36 线程 队列 守护线程 互斥锁 死锁 可重入锁 信号量
    35 守护进程 互斥锁 IPC 共享内存 的方式 生产者消费者模型
    34 进程 pid ppid 并发与并行,阻塞与非阻塞 join函数 process对象 孤儿进程与僵尸进程
    33 udp 域名 进程
    32 粘包 文件传输
    31 socket客户端. 服务器 异常 语法
    30 网络编程
    29 元类 异常
    26 封装 反射 常用内置函数
  • 原文地址:https://www.cnblogs.com/findumars/p/6696912.html
Copyright © 2011-2022 走看看