如果我使用
import MyModule 1.0
我收到一条错误消息,指出 MyModule 未安装。
QQmlApplicationEngine failed to load component
qrc:/main.qml:3:1: module "MyModule" is not installed
但是我正确地编写了qmldir文件和资源文件。 如果我使用
import "MyModule"
一切都可以。但我需要使用不带引号的导入,并将我的模块导入不同目录中的所有文件中。如何正确导入自定义Qml元素?
文件结构
QMLDIRTEST
│ CMakeLists.txt
│ main.cpp
│ main.qml
│ qml.qrc
│
└───MyModule
qmldir
RedRectangle.qml
CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(QmlDirTest VERSION 0.1 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt5 COMPONENTS Core Quick REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick REQUIRED)
set(PROJECT_SOURCES main.cpp qml.qrc)
add_executable(QmlDirTest ${PROJECT_SOURCES})
target_link_libraries(QmlDirTest PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick)
qml.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>MyModule/RedRectangle.qml</file>
<file>MyModule/qmldir</file>
</qresource>
</RCC>
主.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.addImportPath("qrc:/Ui");
engine.load(url);
return app.exec();
}
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import MyModule 1.0
//import "MyModule"
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
RedRectangle { anchors.centerIn: parent }
}
红色矩形.qml
import QtQuick 2.15
Rectangle {
width: 200
height: 100
color: "red"
}
qmldir
Module MyModule
RedRectangle 1.0 RedRectangle.qml
根据文档,需要
addImportPath
来告诉引擎在哪里搜索您提供的新模块。
添加路径作为目录,引擎在基于 URL 的目录结构中搜索已安装的模块。该路径可以是本地文件系统目录、Qt 资源路径 (
)、Qt 资源 URL (:/imports
) 或 URL。qrc:/imports
qt_add_qml_module
函数,您可以使用它仅使用 CMake 添加新模块。此功能会自动生成qmldir
和资源文件。
qt_add_qml_module(${PROJECT_NAME}
URI module.uri
QML_FILES Component1.qml Component2.qml
)
在Qt 6.*中,默认导入路径列表中有一个
qrc:/qt/qml
。通过在 CMake 文件中使用 qt_policy(SET QTP0001 NEW)
,生成的资源(使用 qt_add_qml_module
)将以 /qt/qml
作为默认前缀。这允许引擎检测您的模块,而无需添加任何新的导入路径。 (参考:QTP0001)
您可以通过打印
engine.importPathList()
来检查这一点,您将在输出列表中看到 qrc:/qt/qml
。
qDebug << engine.importPathList();
// Output:
// ("path/to/build-directory/", "path/to/Qt/6.6.1/current-kit/qml", "qrc:/qt-project.org/imports", "qrc:/qt/qml")
您也可以在 Qt 5 中使用相同的技巧。
通过打印
importPathList
,您将看到导入路径列表中有 /qt-project.org/imports
作为默认资源路径:
qDebug << engine.importPathList();
// Output:
QList(
"path/to/build-directory/",
"path/to/Qt/5.15.2/current-kit/qml",
"qrc:/qt-project.org/imports",
)
因此,通过在资源前缀中添加
/qt-project.org/imports
,您可以使引擎识别您提供的模块。例如:
qml.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
<qresource prefix="/qt-project.org/imports">
<file>MyModule/RedRectangle.qml</file>
<file>MyModule/qmldir</file>
</qresource>
</RCC>
为了确保 linter 识别您的模块,您还可以在 CMake 文件中设置
QML_IMPORT_PATH
变量。
list(APPEND QML_DIRS "${CMAKE_SOURCE_DIR}/.")
set(QML_IMPORT_PATH "${QML_DIRS}" CACHE STRING "Qt Creator extra qml import paths")