❝本文介绍,解决使用QtCreator默认创建的一个空的Qml项目工程,从网络中加载Qml控件却一直没效果的问题。❞
1. 问题重现
先看下main.cpp的main函数。
代码语言:javascript复制int main(int argc, char *argv[])
{
...
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty()) {
return -1;
}
return app.exec();
}
我们再看看main.qml文件的内容。
代码语言:javascript复制import QtQuick 2.0
import QtQuick.Window 2.0
/* 从网络导入控件或js */
import "http://qthub.com/qt/qtcomponent"
Window {
visible: true
width: 640
height: 480
title: qsTr("网络加载控件@Qt君")
/* 从网络中加载的控件 */
RoundRectangleDemo { }
}
运行后没效果就退出程序了。
2. 发现问题
经过调试排除Qml网络控件的问题,找到了以下地方导致运行没效果的现象。
代码语言:javascript复制if (engine.rootObjects().isEmpty()) {
return -1;
}
rootObjects()
一直为空,导致程序提前结束了。
3. 分析问题
rootObjects()
为空,那么上一句逻辑执行load()
意味着未正确执行或未加载完成。
查看QQmlApplicationEngine的load函数文档找到以下内容:
代码语言:javascript复制Remote urls are loaded asynchronously, listen to the objectCreated signal to determine when the object tree is ready.
大概意思是「远端链接的加载是异步处理」,可以监听objectCreated
信号以确定对象树何时准备就绪。
最后得出:由于远端链接是异步加载导致rootObjects()
未完成初始化而为空,进而退出了进程。
4. 解决问题
注释下列代码。
代码语言:javascript复制if (engine.rootObjects().isEmpty()) {
return -1;
}
或改成这样:
代码语言:javascript复制QObject::connect(&engine,
&QQmlApplicationEngine::objectCreated,
[&app](QObject *obj, const QUrl &url) {
if (obj == NULL)
app.exit(-1);
});
最后运行的效果: