I\'m confused about modules in Qt QML. I\'ve read all the docs, but it doesn\'t make clear some basic ideas.
I understand that i can put a bunch of QML files into a
I'll try to answer your questions:
QmlExtensionPlugin
for that purpose. You can also use as a module plain QML files in one
directory with a qmldir
describing this module. It is a matter of
distributing your code. With QmlExtensionPlugin
you provide the
module compiled, if you want to hide the code.QML2_IMPORT_PATH
, in directories that you added using engine->addImportPath()
There are a bunch of things that can lead to a module not being loaded. You can check the following:
qmldir
should be the same as the directory
name, where the module actually resides. For example if your module
has module identifier module Test.Module
in qmldir
, your module's
relative path must be Test/Module
.QML2_IMPORT_PATH
(make sure there is 2
in the name) env variable to point to directory containing your module. There is also a QQmlEngine::addImportPath
method, which adds the directory to the list to lookup for plugins.ldd
command on Linux.QT_PLUGIN_PATH
runtime variable may help to load plugins. It should point to a directory containing you plugin's directory, not the plugin's directory itself.QT_DEBUG_PLUGINS=1
and QML_IMPORT_TRACE=1
environment variablesYou can also read this link: https://doc.qt.io/qt-5/qtqml-modules-identifiedmodules.html
I want to expand on arxarian's answer - which I think is the best technique for integrating modules - but couldn't fit those thoughts in a comment, so here's a new answer.
It's important to first understand that qml modules and their associated resources are runtime entities and are assumed to separately exist at some location relative to the executable unless they're included in the application resources. By including them in the resources, they are still runtime entities, but they exist under the qrc:/ root path within the application binary. This hiding of the modules is the primary reason why I think this is the best technique, unless you want your modules to be open to revision after deployment, or to be independently deployable as precompiled plugins (i.e., in the resource storage of a dynamically linked library).
So here's my explanation of the important elements of arxarian's answer:
engine.addImportPath("qrc:/");
is needed in the C++ code prior to loading the qml to instruct the engine to look for qml modules in the application resource storage.RESOURCES += MyModule/mymodule.qrc
is needed in the project (.pro) file to add the module's files to the application resource storage.QML_IMPORT_PATH += $$PWD
in the project file tells Qt Creator to look for the module starting from the root of the project source tree. In my case I had to set this to a subdirectory (e.g., "ui/modules") because my module directories started there. The import path should include the root(s) beneath all module directories. As far as I can tell, this instruction is only for the Qt Creator IDE and does not impact the build - that's why #1 is needed.<qresource prefix="/MyModule">
in the module's .qrc file defines the module subdirectory relative to the qrc:/ root in the application resource storage.import MyModule <version>
statement in qml is now setup for success. On startup the engine will have located the module in its directory under qrc:/, parsed the qmldir file there to define the module and established the name and version from those entries.Hopefully this helps others understand what's going on, and please let me know if I've misunderstood anything.
In my case (I have all QML files in qrc resources) worked to add qmldir to resources also and call method addImportPath("qrc:/") of QQmlApplicationEngine.
My main.cpp looks like:
QQmlApplicationEngine engine;
engine.addImportPath("qrc:/");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
Important parts of my .pro file looks like:
RESOURCES += qml.qrc \
MyModule/mymodule.qrc
QML_IMPORT_PATH += $$PWD
My qmldir:
module MyModule
MyItem 2.0 MyItem20.qml
MyItem 2.1 MyItem21.qml
My qrc:
<RCC>
<qresource prefix="/MyModule">
<file>MyItem20.qml</file>
<file>MyItem21.qml</file>
<file>qmldir</file>
</qresource>
</RCC>
And finally my 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 is happy (not underlining components and imports) and module is loaded. Hope this helps.
A similar issue cost me a bit of time so I just post it here to perhaps save the next guy some effort.
My problem was that an invisible character had sneaked into the module name. Probably through copy and paste. Here my issue:
Example error output:
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
It all looks fine and the path displayed is indeed the correct one. So what is wrong?
Now, copy that path to a Terminal window:
file:///Users/<pathToProject>/MyProject/qml/MyModule/<feff>MyComponent.qml
There it is, the:
"<feff>"
Solved the issue by manually retyping the component name in the qmldir file, and thus effectively deleting the invisible character.
I had the same problem and have now fixed it. I found a QML plugin for iOS. There are several things that need to be taken care of:
1. The plugin pro file needs an addition:
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. The QML plugin qmldir file needs an additional line like this:
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 The client project pro file needs an addition like this:
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