QT Demo 之 window(3) Qt.quit()

在上一章《QT Demo 之 window(2) Splash》学习中留下一个TODO没有解决,就是在示例代码中有这样的一段:

        MouseArea {
            anchors.fill: parent
            onClicked: Qt.quit()
        }
其本意就是在显示Splash Screen的时候,如果点击Splash Screen图片就会退出整个程序,但实际结果就是报了一行错误:
Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.
程序仍然好好的进行着。

我们使用上面的错误提示信息作为关键字进行搜索,通过bing搜索找到的只有一个有效页面Qt Error: Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it,在该页面中提到了正确的使用quit()的语法是:

connect(sender, SIGNAL(signalName(args)), receiver, SLOT(slotName(args)));

看到这里我是感觉到头痛了,这个什么和什么呢?说的语焉不详的,完全不知道怎么解决当前这个Demo的问题。

从帮助文档入手

那么就从Qt的帮助文档开始,先了解一下quit()函数的官方说明:
quit()
This function causes the QQmlEngine::quit() signal to be emitted. Within the Prototyping with qmlscene, this causes the launcher application to exit; to quit a C++ application when this method is called, connect the QQmlEngine::quit() signal to the QCoreApplication::quit() slot.

帮助文档中提到,如果要退出一个C++的应用程序,需要connect the QQmlEngine::quit() signal to the QCoreApplication::quit() slot.

这个时候我们就知道在上面提到了connect()函数调用就有关联了。

Qt.quit()示例代码

我们再次使用Qt.quit()作为关键字在bing上搜索,找到一个Closing a Qt Quick application from QML页面。

在示例代码中我们看到调用Qt.quit()函数的地方也是在Qml的MouseArea控件中通过onClicked事件响应函数中完成的,但是和Window示例代码中不同的地方在main.cpp中:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
 
    QDeclarativeView view;
    view.setSource(QUrl("./ui.qml"));
    view.setResizeMode(QDeclarativeView::SizeRootObjectToView);
 
    <span style="color:#FF0000;">QObject::connect((QObject*)view.engine(), SIGNAL(quit()), &app, SLOT(quit()));</span>
 
    view.setGeometry(100,100, 800, 480);
    view.show();
 
    return app.exec();
}
注意,上面的红色部分,这个应该就是问题的关键。

因此,仿照这个示例代码,我们在Window示例项目的main.cpp中添加了下述代码:

    QObject::connect(&engine, SIGNAL(quit()), &app, SLOT(quit()));

再次运行程序,在Splash Screen出现的时候,单击鼠标左键,奇迹出现了:程序按照预期退出了

再次回到刚才的Closing a Qt Quick application from QML页面中,我们看到由下述的一行解释:
The calling of the Qt.quit() function in QML code caused the emission of the QDeclarativeEngine::quit() signal, and because this signal was connected to the QApplication::quit() slot, the application was closed.

看到这里,我们才了解到,原来在Qml中调用Qt.quit()函数,只是触发了一个QDeclarativeEngine::quit()的信号,在原来的代码中,由于没有任何地方处理这个信号,就会报出no receivers connected to handle it的错误,而通过添加QObject::connect(&engine, SIGNAL(quit()), &app, SLOT(quit()));代码后,就是把QDeclarativeEngine::quit()信号和QApplication::quit()方法关联起来了,最终会导致程序完全退出。

看到这里吐槽一句,其实默认的QDeclarativeEngine::quit()的信号就应该和QApplication::quit()方法关联起来,作为一种default的处理方法,如果需要自定义处理退出模式的话再通过一些方法来完成,而不是留下这样的一个坑。

扩展阅读

在检索资料时也看到了一些好的博客,总结的很好,推荐给大家:

Qt学习经验之quit()、exit()、close():详细讲解了Qt中的quit()、exit()、close()函数区别,并给出了如何自定义退出时的UI处理方法。

Qt--help:博客的名字虽然是Qt--help,但是实际上讲解了QObject::connect()函数,不算深入,但是可以稍微了解一下

总结

这一章只是解决了上一章中留下的一个TODO,初步学习了一下QObject::connect()函数。

只是在解决这个TODO的过程中,感觉Qt的示例代码以及帮助文档做得还是不够太好,而这也不是第一次被坑了。

QT Demo 之 window(3) Qt.quit()

上一篇:新发现:AirDroid(用Web端控制自己的手机发信息)


下一篇:C#:实现快捷键自定义设置