如何为 qtquick 插件添加 qrc 导入路径?

How can I add the qrc import path for qtquick plugin?

我已经构建了一个静态 Qt 库并希望使用它通过独立的 exe 部署我的应用程序。经过一天的努力,我知道qtquick插件不能静态包含到exe中。

我需要将 qml 文件夹中的一些文件夹复制到我的 exe 目录,让 exe 可以显示 GUI。

所以我想知道我的exe需要哪个文件,我把那些文件夹里的文件一个一个删了才知道。真正需要的文件只是一个plugins.QMLTYPES文件和一个qmldir文件。

然后我发现QQmlApplicationEngine的导入路径可以改变,我输出QQmlApplicationEngine.importPathList(),其中一个路径就是Qt安装路径中的qml文件夹。 所以我认为这是Qt获取plugins.QMLTYPES文件和qmldir文件的搜索路径的地方。

如果我认为是正确的,我可以将我需要的文件夹复制到qrc文件中,然后使用QQmlApplicationEngine.addImportPath("qrc:/foldersIwant")让exe可以在运行时间导入它需要的东西。而且因为 qrc 被编译成 exe,我可以摆脱那些文件夹,让我的 exe 独立。

但是在我的代码中这样做之后,应用程序仍然找不到它需要的文件,即使 QQmlApplicationEngine.importPathList() 的输出有我输入的路径,我也根据 [=27 检查了我的路径=].

代码如下:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;

    engine.addImportPath(QStringLiteral("qrc:/import/qtquick/"));
    qDebug()<<engine.importPathList();

    engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));

    return app.exec();
}

这是我的 qrc 文件的一部分

我的演绎有问题吗?

进一步研究:

我已经添加 engine.addImportPath(QDir::currentPath() + QDir::separator() + "custom");

并将所有文件夹移动到custom文件夹中,可以运行成功。而没有这行的exe不能运行和custom文件夹。所以我想知道 "search" 行为不能应用于 qrc 文件?

终于,我得到了答案。结果证明我所有的想法都是正确!

以下是我尝试过的方法,您可以阅读结尾以获得清晰的步骤。

我的目标是编译一个独立的 qml2 应用程序 exe。

在 qml1 中,我可以构建静态 Qt 库并用它编译我的应用程序。

在qml2中,exe可以用同样的方式编译。但是如果我 运行 它没有 Qt-Runtime。它只是没有在 Windows OS 上显示任何 window(并且在其他 OS 上也没有显示任何内容)。 google了很多资料,发现这个问题从Qt5.0开始就困扰了很多人。现在是Qt5.5了,他们还没有修复。 所以我需要将 QT_INSTALLED_PREFIX/qml 中的文件夹复制到我的应用程序的根目录,让我的应用程序显示 GUI。

虽然问题会在Qt5.6(https://codereview.qt-project.org/#/c/114835/)中得到解决,但我等不了这么久了(Qt5.6将在今年年底发布)。所以我决定自己打包文件。

偶然看到这个问题:。它告诉我 qmldir 文件可以包含到 qrc 文件中,Qml 引擎可以搜索到那些目录。所以我认为,QML 文件也可以包含到 qrc 文件中。

但首先要找到导入qml2的地方,当我查看QQmlApplicationEngine的文档时,我发现了addImportPath函数,我告诉自己这一定是找到导入路径的关键。文件告诉我一切:

QStringList QQmlEngine::importPathList()
const Returns the list of
directories where the engine searches for installed modules in a
URL-based directory structure.

For example, if /opt/MyApp/lib/imports is in the path, then QML that
imports com.mycompany.Feature will cause the QQmlEngine to look in
/opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
provided by that module. A qmldir file is required for defining the
type version mapping and possibly QML extensions plugins.

By default, the list contains the directory of the application
executable, paths specified in the QML2_IMPORT_PATH environment
variable, and the builtin Qml2ImportsPath from QLibraryInfo.

我在运行时删除了importPathList中的Qml2ImportsPath后,又重现了app不显示任何GUI的bug

addImportPath的文档告诉我可以接受qrcurl。所以我就把qml里的所有文件都加进去,就像上面描述的问题一样。但是我还是看不到任何GUI。

经过几天的思考。我发现我发布的有问题的图片没有 qmldir 文件!那是 Qt Creator 的一个错误。我使用 Add Existing Directory... 添加文件并将过滤器设置为 *,它仍然不能包含 qmldir 文件。所以我通过 xml 代码将它添加到 qrc 文件中。

当我认为这次它必须工作时,它却什么也没给我。就在我打算放弃的时候,一个念头冒了出来:不会浪费我更多的时间来检查qrc:/import/qtquick/是否有效。

结果是false,一定是我的qrc用法有误。我更改前缀并使用 Qt Creator 保存 qrc。我发现qrc文件不能使用像D:/Qt/Qt-5.5-static/qml/Qt/labs/folderlistmodel/plugins.qmltypes这样的路径,它被Qt Creator改为Qt/labs/folderlistmodel/plugins.qmltypes。此时,一切正常!

感谢您阅读我的故事。以下是解决此问题的步骤总结:

  1. 将QT_INSTALLED_PREFIX/qml中的所有文件夹复制到您的项目文件夹中,最好将它们放在父文件夹下而不是根文件夹下。
  2. 写一些代码来获取除 .lib 文件之外的所有文件的相对路径和 .prl 个文件。
  3. 创建一个新的 .qrc 文件并将其包含在 .pro 文件中。将所有文件包含到此 .qrc 文件中。我写了一个小程序来生成 xml.
  4. 使用QQmlApplicationEngineaddImportPath方法添加导入路径。
  5. 建造并享受。