【问题标题】:How to do things upon quitting a Qt app如何在退出 Qt 应用程序时做一些事情
【发布时间】:2014-07-21 11:33:06
【问题描述】:

据我了解,以下将执行一个应用程序,该应用程序将在所有相关窗口关闭时退出。

int main(int argc, char *argv[])
{
    QApplication cal(argc, argv); //Application instance

    MainWindow window; //Create window in the stack
    window.show(); //Show the window

    return cal.exec(); //Execute event loop
}

这也将退出所述应用程序。

quitButton = new QPushButton("Quit", this);

connect(quitButton, SIGNAL(clicked()), QApplication::instance(), SLOT(quit()));

我应该如何进行清理(关闭硬件连接和库等),以便我可以确保无论应用程序如何退出,也无论它在执行的哪个时间点退出,需要发生的一切都会发生?

我将在整个应用程序中打开一个库,并在大多数情况下连接到 USB 设备。如果进程运行正常,我可以轻松关闭此连接,但如果有人决定在完成之前点击退出或关闭所有窗口,我希望安全关闭连接。

【问题讨论】:

  • 您可以从 QApplication 继承,并在析构函数中进行清理。否则,连接到 QCoreApplication::aboutToQuit 信号。
  • 我想过添加一个aboutToQuit,但认为如果有人只是关闭窗口而不是点击退出按钮,这将行不通。

标签: c++ qt dll usb qt-creator


【解决方案1】:

QWidget 有一个名为closeEvent 的虚函数(参见Documentation,它在小部件close() 操作被调用时被调用。

或者,如果您不想拥有自己的 Base 小部件,您可以将自己连接到信号 QApplication::lastWindowClosed(请参阅 here)。它在您的应用程序的最后一个可见窗口关闭时发出。

【讨论】:

  • 我是否认为只要应用程序以任何方式退出,就会在上面的窗口对象上调用close() 操作?
  • 仅当您以 Qt 方式退出时。这包括调用close() 或使用窗口上的关闭按钮的任何Qt 函数。如果你杀死你的应用程序(例如在调试器中),它不会被调用。
  • 只是为了澄清当您说窗口上的关闭按钮时,您是指右上角的红十字吗?我想如果不处理从调试器、任务管理器等退出,我会没事的。
  • 是的。红色 X 只会触发关闭事件,例如您的按钮。对于 Qt 并没有太大区别。
【解决方案2】:

您可以执行以下操作:

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

    // Allocate resources

    int ret = cal.exec(); // start the event loop and wait until it quits

    // Free the resources

    return ret;
}

【讨论】:

  • 无论应用程序如何停止,这都会执行?
  • 如果你正常退出 - 是的。
  • 漂亮而简单。我认为这比所有 Qt 钩子更受欢迎,特别是如果资源已经在主函数中分配了
  • 我想我会用它来卸载 dll,尽管我可能会使用下面的 @MatthiasB 的建议关闭 USB 连接,以避免不必要地传递标识符
  • 这就是你在 C 中的做法,而不是 C++。
【解决方案3】:

正确的 C++ 方法是:

  1. 确保您的所有对象实例都被破坏。

  2. 确保您持有的任何资源都通过RAII 持有。

那么你不需要做任何特别的事情。当main 返回时,对象会被破坏,所以事情会被清理干净。

例如:

int main(int argc, char ** argv) {
  QApplication app(argc, argv);
  QObject foo;
  QObject * bar = new QObject(&app);
  Widget w;
  w.show();
  return app.exec();
}

在这里,foobarmain 返回之前被正确破坏。现在假设你持有一些非内存资源,比如一个文件:

class Worker : public QObject {
  QFile m_file;
  ...
  void doSomething() {
    if (m_file.open()) {
      ...
    }
    // No file closing!
  }
};

int main(int argc, char ** argv) {
  QApplication app(argc, argv);
  Worker foo;
  Widget w;
  w.show();
  return app.exec();
}

同样,文件在main 返回之前关闭。

简而言之,这就是 RAII 的工作原理。如果您有自己的类来包装操作系统或其他资源,只需确保在类被破坏时释放这些资源 - 并且这些类始终可破坏(破坏它们总是安全的)。我最讨厌的是QThread - 它打破了这个预期,你必须implement a wrapper 来修复它。

对于需要在堆上分配的资源,您应该使用智能指针或QObject 内存管理。

【讨论】:

    【解决方案4】:

    有一个 QApplication 信号可用于在应用程序退出之前进行清理:

    QObject::connect(&app, SIGNAL(aboutToQuit()), &MyCleaner, SLOT(cleanUp()));

    玩得开心!

    【讨论】:

      猜你喜欢
      • 2014-01-09
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多