QDialog exec()无法退出进程

时间:2014-08-28 09:44:04

标签: qt exec qdialog

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QDialog dlg;
    dlg.exec();
    return a.exec();
}

这就是我的所有代码,但当我关闭窗口时,进程不会退出,它似乎会在循环a.exec()中出现。

2 个答案:

答案 0 :(得分:4)

一般来说,除了QCoreApplication::exec()QDrag::exec()之外,调用任何 exec都是个坏主意。 exec()waitForXxx()方法的存在对于粗心大意来说是一个诱人的陷阱。这些方法“易于使用”,但这种方法的代价是难以追踪错误。不要使用它们。

您应该只显示对话框:

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

如果您希望等待接受或拒绝对话,则应使用对话框的clickedButton插槽。 QMessageBox有一个长期存在的错误,导致acceptedrejected信号失效:(

// 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"

对于Qt 4,您需要以下帮助程序:

// 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();
   }
};

答案 1 :(得分:0)

可能的解决方案:

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

它会很好用。首先 - 将启动应用程序事件循环。然后执行对话框事件循环。关闭对话框后,对话框和应用程序循环都将完成。当最后一个窗口关闭时,应用程序循环将自动终止(默认情况下)。

但是,如@thuga所述 - 没有理由打电话给exec()。只需调用show()方法即可。