如何fully/correctly 从主窗体退出Qt 程序?

How to fully/correctly exit a Qt program from the main form?

我正在编写一个 Qt 程序(使用 Qt 5.4),它基于 QTimer 从网络摄像头读取帧,而不是一个单独的线程(间隔设置为 20 毫秒,当然它需要比 1/50 更长的时间一秒钟从网络摄像头读取帧并处理它,我估计帧速率可能是 20 fps。无论如何,当定时器循环时运行的函数是一个插槽,如下所示:

///////////////////////////////////////////////////////////////////////////////////////////////////
void frmMain::processFrameAndUpdateGUI() {

bool blnFrameReadSuccessfully = capWebcam.read(matOriginal);      // get next frame from the webcam

if (!blnFrameReadSuccessfully || matOriginal.empty()) {           // if we did not get a frame
    QMessageBox::information(this, "", "unable to read from webcam \n\n exiting program\n");
    QApplication::quit();
}

// process frame here . . .

想法是如果网络摄像头可以在程序开始时成功读取,但之后就不能(网络摄像头停止工作,用户不小心断开网络摄像头等)程序应该显示一个消息框来达到这个效果,并且然后完全关闭自己。

在上述情况下,如果我在程序 运行 出于测试目的拔下网络摄像头,消息框会按预期显示,但在选择“确定”后,会出现调试错误屏幕。如果我选择 "Abort" 表单仍然存在并且不会响应。在多次尝试关闭表单后,Windows 询问 "the program does not seem to be responding, would you like to close?" 我何时可以关闭表单。显然这没有达到预期的效果。

经过各种谷歌搜索,我发现建议修改如下:

///////////////////////////////////////////////////////////////////////////////////////////////////
void frmMain::closeEvent(QCloseEvent *) {
    QApplication::quit();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
void frmMain::processFrameAndUpdateGUI() {

bool blnFrameReadSuccessfully = capWebcam.read(matOriginal);      // get next frame from the webcam

if (!blnFrameReadSuccessfully || matOriginal.empty()) {           // if we did not get a frame
    QMessageBox::information(this, "", "unable to read from webcam \n\n exiting program\n");
    closeEvent(new QCloseEvent());
}

// process frame here . . .

当我第一次看到这段代码时,我很乐观,但它给了我与上面相同的结果(程序挂起,表单仍然打开)。我正在使用 OpenCV 2.4.11 进行图像处理,我的程序有 4 个文件:

是的,我知道我可以在一个可以显示文本的小部件上显示一条错误消息,return 来自函数,然后让用户关闭程序,但我寻找更优雅的解决方案。任何人都可以就如何完全关闭图形 Qt 程序提供进一步的建议吗?请指教

有两件事可以解决您的问题:

  1. 在显示消息框之前,使用stop()方法停止计时器。
  2. QApplication::quit(); 退出函数后 return; 你的函数可能是 运行 最后一次结束并访问无效对象。

对于其他人的参考,Rafael Monteiro 的回答很准确。这是更新后的代码(已验证有效):

///////////////////////////////////////////////////////////////////////////////////////////////////
void frmMain::closeEvent(QCloseEvent *) {
    if(qtimer->isActive()) qtimer->stop();      // had to stop timer here !!!!!!!!
    QApplication::quit();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
void frmMain::processFrameAndUpdateGUI() {
    bool blnFrameReadSuccessfully = capWebcam.read(matOriginal);                    // get next frame from the webcam

    if (!blnFrameReadSuccessfully || matOriginal.empty()) {                            // if we did not get a frame
        QMessageBox::information(this, "", "unable to read from webcam \n\n exiting program\n");
        closeEvent(new QCloseEvent());
        return;          // had to add return here !!!!!!!!!
    }

    // rest of function here . . .

我应该提到我必须同时添加 return 并停止计时器。谢谢拉斐尔!