如何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 个文件:
- frmmain.h(主窗体.h,是用Qt Creator制作的标准QMainWindow)
- frmmain.cpp(主窗体.cpp,上面代码所在)
- main.cpp(我没有改变 Qt Creator 的制作方式)
- frmmain.ui(典型形式加上少量通过Qt Creator添加的常用widgets)
是的,我知道我可以在一个可以显示文本的小部件上显示一条错误消息,return 来自函数,然后让用户关闭程序,但我寻找更优雅的解决方案。任何人都可以就如何完全关闭图形 Qt 程序提供进一步的建议吗?请指教
有两件事可以解决您的问题:
- 在显示消息框之前,使用stop()方法停止计时器。
- 在 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 并停止计时器。谢谢拉斐尔!
我正在编写一个 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 个文件:
- frmmain.h(主窗体.h,是用Qt Creator制作的标准QMainWindow)
- frmmain.cpp(主窗体.cpp,上面代码所在)
- main.cpp(我没有改变 Qt Creator 的制作方式)
- frmmain.ui(典型形式加上少量通过Qt Creator添加的常用widgets)
是的,我知道我可以在一个可以显示文本的小部件上显示一条错误消息,return 来自函数,然后让用户关闭程序,但我寻找更优雅的解决方案。任何人都可以就如何完全关闭图形 Qt 程序提供进一步的建议吗?请指教
有两件事可以解决您的问题:
- 在显示消息框之前,使用stop()方法停止计时器。
- 在 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 并停止计时器。谢谢拉斐尔!