如何使用 qmldir 和 QML 模块导入自定义 QML 元素

问题描述 投票:0回答:1

如果我使用

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
qt qml
1个回答
0
投票

根据文档,需要

addImportPath
来告诉引擎在哪里搜索您提供的新模块。

QQmlEngine::addImportPath 状态:

添加路径作为目录,引擎在基于 URL 的目录结构中搜索已安装的模块。该路径可以是本地文件系统目录、Qt 资源路径 (

:/imports
)、Qt 资源 URL (
qrc:/imports
) 或 URL。

Qt 6.* 之后,CMake 中有一个

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.* 解决方案

您也可以在 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")
© www.soinside.com 2019 - 2024. All rights reserved.