如何从主窗体完全/正确退出Qt程序?

时间:2015-05-25 02:29:33

标签: c++ qt opencv

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

#img { max-width: 100%; }

想法是如果网络摄像头可以在程序开头成功读取,但不能(网络摄像头停止工作,用户意外断开网络摄像头等)程序应该显示一个消息框,然后关闭本身完全。

如上所述,如果我在程序运行时拔出网络摄像头以进行测试,则会出现预期的消息框,但选择确定后会出现调试错误屏幕。如果我选择“中止”,表单仍然存在且不会响应。在尝试多次关闭表单后,Windows会询问“该程序似乎没有响应,您想要关闭吗?”那时我可以关闭表格。显然,这并没有达到预期的效果。

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

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

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

  • frmmain.h(.h为主窗体,是用Qt Creator制作的标准QMainWindow)
  • frmmain.cpp(主窗体的.cpp,上面代码所在的位置)
  • main.cpp(我没有改变Qt Creator如何制作它)
  • frmmain.ui(通过Qt Creator添加少量常用小部件的典型表单)

是的,我意识到我可以在其中一个可以显示文本的小部件上显示错误消息,从函数返回,并将其留给用户关闭程序,但我正在寻找更优雅的解决方案。任何人都可以提供有关如何完全关闭图形Qt程序的进一步建议吗?请指教。

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

对于其他任何人的参考,拉斐尔·蒙泰罗的回答都是现实的。这是更新的代码(经过验证的工作):

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

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