Qml加载网络控件之小坑

2023-03-17 13:49:45 浏览数 (3)

❝本文介绍,解决使用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);
                 });

  最后运行的效果:

1 人点赞