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的示例代碼以及幫助文檔做得還是不夠太好,而這也不是第一次被坑了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章