QDialog exec() can not exit process

 ̄綄美尐妖づ 提交于 2019-12-06 15:53:05

Generally speaking, calling any exec is a bad idea, other than QCoreApplication::exec() or QDrag::exec(). The presence of exec() and waitForXxx() methods is an enticing trap for the unwary. Those methods are "easy" to use, but that ease comes at a price of hard to track bugs. Don't use them.

You should simply show the dialog:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QMessageBox msg;
    msg.setText("Hello");
    msg.addButton(QMessageBox::Close);
    msg.show();
    return a.exec();
}

If you wish to wait for the dialog to be accepted or rejected, you should use the dialog's clickedButton slot. QMessageBox has a long-standing bug that makes the accepted and rejected signals useless :(

// https://github.com/KubaO/stackoverflown/tree/master/questions/messagebox-show-25545652
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif
#include <functional>

[...]

int main(int argc, char *argv[])
{
   QApplication app(argc, argv);

   QMessageBox msg;
   msg.setText("Continue?");
   msg.addButton(QMessageBox::Yes);
   msg.addButton(QMessageBox::No);
   auto onClick = [&msg]() {
      auto role = msg.buttonRole(msg.clickedButton());
      if (role == QMessageBox::NoRole)
         QApplication::quit();
      if (role == QMessageBox::YesRole) {
         auto label = new QLabel("I'm running");
         label->setAttribute(Qt::WA_DeleteOnClose);
         label->show();
      }
   };
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
   QObject::connect(&msg, &QMessageBox::buttonClicked, onClick);
#else
   QObject::connect(&msg, SIGNAL(buttonClicked(QAbstractButton*)),
                    new FunctorSlot{onClick, &msg}, SLOT(call()));
#endif
   msg.show();
   return app.exec();
}
#include "main.moc"

For Qt 4, you need the following helper:

// Qt 4 only
struct FunctorSlot : public QObject {
   Q_OBJECT
public:
   std::function<void()> callable;
   template <typename Fun>
   FunctorSlot(Fun && fun, QObject * parent = {}) :
      QObject{parent}, callable{std::forward<Fun>(fun)} {}
   Q_SLOT void call() {
      callable();
   }
};

Possible solution:

QApplication a(argc, argv);
QDialog dlg;
QTimer::singleShot( &dlg, 0, SLOT(exec()) );
return a.exec();

It will work well. First - application event loop will be started. Then dialog event loop will be executed. After closing of dialog, both dialog and application loop will be finished. Application loop will be terminated automatically (by default), when last window is closed.

But, as noted by @thuga - there are no reason to call exec(). It is enough to call show() method.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!