Qt5没有安装QML模块

时间:2016-02-12 00:50:39

标签: qt qml qt5

我对Qt QML中的模块感到困惑。我已经阅读了所有文档,但它没有说明一些基本的想法。

据我所知,我可以将一堆QML文件放入目录并添加qmldir文件来描述已识别的模块。当我这样做并调整QML_IMPORT_PATH时,QtCreator很高兴并停止强调导入ModuleName 1.0行。

所以创作者很高兴,但它不起作用。我没有安装模块。 我的问题是:

  • “已安装”是什么意思。我有文件目录,但我没有在任何地方“安装”它们。
  • 我应该构建/编译模块来制作DLL / .so?
  • 模块QML文件是否会进入主应用程序的资源,否则它们会在哪里找到?
  • 我的main.qml文件是应用资源的一部分,应用程序如何在运行时找到模块的资源。

对不起,对于所有这些问题,但这些模块的基础知识并不清楚。我不明白“模块”是仅仅是文件共享还是编译单元。

感谢您的帮助。

5 个答案:

答案 0 :(得分:9)

我会尽力回答你的问题:

  • 我认为已安装意味着它们位于正确的路径中,所以
    它们可以在运行时找到
  • 您不一定要为此目的创建/构建QmlExtrensionPlugin。您还可以将模块中的普通QML文件合二为一 带有描述此模块的qmldir的目录。这是问题 分发您的代码 - 使用您提供的QmlExtensionPlugin 模块编译,如果你想隐藏代码。
  • 这些模块可以在资源系统中,也可以作为磁盘上的文件,由您决定。
  • 应用程序在预定义路径中查找模块 - 在应用程序目录中,QT插件路径中,QML2_IMPORT_PATH中,使用engine->addImportPath()
  • 添加的目录中

有很多东西可能会导致模块无法加载。您可以查看以下内容:

  1. qmldir中的模块标识符应与目录相同 name,模块实际驻留的位置。例如,如果你的模块 在模块qmldir中有模块标识符module TestModule 目录名称必须为TestModule
  2. 如果是QML扩展名 插件(共享库),确保插件的目录名是 与插件的名称相同。
  3. 导出QML2_IMPORT_PATH(确保名称中有2)env变量指向包含模块的目录。还有一个QQmlEngine::addImportPath方法,它将目录添加到列表中以查找插件。
  4. 如果它是qml扩展插件(共享库),则可能缺少它的依赖项。您可以通过Windows上的Dependency Walker或Linux上的ldd命令进行检查。
  5. 设置QT_PLUGIN_PATH运行时变量可能有助于加载插件。它应该指向一个包含插件目录的目录,而不是插件目录本身。
  6. 您还可以启用跟踪,以便在加载插件时查看正在进行的操作,以便更好地了解问题 - 导出QT_DEBUG_PLUGINS=1QML_IMPORT_TRACE=1环境变量
  7. 您还可以阅读以下链接: https://doc.qt.io/qt-5/qtqml-modules-identifiedmodules.html

答案 1 :(得分:8)

在我的情况下(我在qrc资源中有所有QML文件)也努力将qmldir添加到资源中,并调用QQmlApplicationEngine的方法addImportPath(" qrc:/")。

我的main.cpp看起来像:

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

我的.pro文件的重要部分如下:

RESOURCES += qml.qrc \
    MyModule/mymodule.qrc

QML_IMPORT_PATH += $$PWD

我的qmldir:

module MyModule

MyItem          2.0 MyItem20.qml
MyItem          2.1 MyItem21.qml

我的qrc:

<RCC>
    <qresource prefix="/MyModule">
        <file>MyItem20.qml</file>
        <file>MyItem21.qml</file>
        <file>qmldir</file>
    </qresource>
</RCC>

最后我的main.qml:

import QtQuick 2.5
import QtQuick.Window 2.2

import MyModule 2.0

Window {
    visible: true
    width: 640
    height: 480

    MyItem {
        anchors.fill: parent
    }
}

QtCreator很高兴(没有强调组件和导入)并加载了模块。 希望这会有所帮助。

答案 2 :(得分:3)

我希望扩展arxarian's answer - 我认为这是整合模块的最佳技巧 - 但不能将这些想法纳入评论中,所以这是一个新答案。

首先要了解qml模块及其相关资源是运行时实体,并假设它们分别存在于相对于可执行文件的某个位置,除非它们包含在应用程序资源中。通过将它们包含在资源中,它们仍然是运行时实体,但它们存在于应用程序二进制文件中的qrc:/ root路径下。这种模块的隐藏是我认为这是最好的技术的主要原因,除非你希望你的模块在部署后开放修改,或者可以独立部署为预编译插件(即,在动态链接的资源存储中)库)。

所以这是我对arxarian's answer的重要元素的解释:

    在加载qml之前,C ++代码中需要
  1. engine.addImportPath("qrc:/");,以指示引擎在应用程序资源存储中查找qml模块。
  2. 项目(.pro)文件中需要
  3. RESOURCES += MyModule/mymodule.qrc将模块的文件添加到application resource storage
  4. 项目文件中的
  5. QML_IMPORT_PATH += $$PWD告诉 Qt Creator 从项目源树的根开始查找模块。在我的情况下,我必须将其设置为子目录(例如,“ui / modules”),因为我的模块目录在那里开始。导入路径应包括所有模块目录下的根。据我所知,这条指令仅适用于Qt Creator IDE,不会影响构建 - 这就是为什么需要#1的原因。
  6. qmldir文件的内容与standard for all qml modules一样,但是在您考虑运行时存储发生的情况之前,它包含在模块的.qrc资源文件中并不直观。它需要位于.qrc中,以便它包含在应用程序资源存储中,以便引擎可以在运行时找到它来定义模块。模块的.qrc文件中的<qresource prefix="/MyModule">定义了相对于应用程序资源存储中的qrc:/ root的模块子目录。
  7. qml中的import MyModule <version>语句现已成功设置。启动时,引擎会将模块放在qrc:/下的目录中,解析qmldir文件以定义模块并从这些条目中建立名称和版本。
  8. 希望这有助于其他人了解正在发生的事情,如果我误解了任何内容,请告诉我。

答案 3 :(得分:0)

类似的问题花了我一些时间,所以我只在这里发布它,也许可以节省下一个家伙的精力。

我的问题是一个不可见的字符潜入了模块名称。可能通过复制和粘贴。这是我的问题:

错误输出示例:

MyEngine failed to load component
qrc:/qml/main.qml:53 Type MyComponent unavailable
file:///Users/<pathToProject>/MyProject/qml/MyModule/MyComponent.qml:-1 No such file or directory

一切看起来不错,显示的路径确实是正确的路径。那怎么了?

现在,将该路径复制到“终端”窗口:

file:///Users/<pathToProject>/MyProject/qml/MyModule/<feff>MyComponent.qml

就在这里,

"<feff>"

通过手动重新键入qmldir文件中的组件名称来解决此问题,从而有效地删除了不可见字符。

答案 4 :(得分:-1)

我遇到了同样的问题,现在已经解决了。我找到了一个适用于iOS的QML插件。有几件事需要注意:

<强> 1。插件专业版文件需要添加:

  

uri = IosTestPulgin

# this for error:
# static plugin for module “QtQuick” with name “IosTestPulgin” 
# has no metadata URI
QMAKE_MOC_OPTIONS += -Muri=$$uri

# thanks from:https://github.com/wang-bin/QtAV/issues/368

<强> 2。 QML插件qmldir文件需要一个额外的行,如下所示:

classname IosqmlpluginPlugin
# for ERROR: Plugin iostestqmlplugin is missing a classname entry,
# please add one to the qmldir file.
# look for qt document http://doc.qt.io/qt-5.6/qtqml-modules-qmldir.html

3客户端项目专业文件需要添加如下内容:

ios {
    IOSTestPlugin_BUNDLE.files += $$files($$[QT_INSTALL_QML]/IosTestPulgin/qmldir)
    IOSTestPlugin_BUNDLE.path =  IosTestPulgin
    QMAKE_BUNDLE_DATA += IOSTestPlugin_BUNDLE
}
# for ios error: module is not installed
# this means external qml static plugin must add the plugin dir by manual
# in the app root dir