加载的组件引用另一个内部组件时如何使用QML Loader

How to use QML Loader when the loaded component references another internal component

我在 https://github.com/jh3010-qt-questions/qml_location/tree/loader_with_another_component

有一个仓库

我正在使用加载程序将 MyDeeperComponent 加载到 main.qml 的列中。然而,MyDeeperComponent 引用另一个名为 MySquare 的内部组件。加载时,我收到错误 MySquare is not a type 并且程序退出。当然,如果我从 MyDeeperComponentForm.ui.qml 注释掉 MySquare,一切正常,MyDeeperComponent 加载成功。

需要更改什么才能使 MyDeeperComponent 可以使用 MySquare 并动态加载?

目录结构为:

$ tree qml_location/
qml_location/
├── MySquare.qml
├── MySquareForm.ui.qml
├── main.cpp
├── main.qml
├── qml
│   └── more
│       ├── MyDeeperComponent.qml
│       └── MyDeeperComponentForm.ui.qml
├── qml.qrc
├── qml_location.pro
└── qml_location.pro.user

qml_location.pro

QT += quick

CONFIG += c++11

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp

RESOURCES += qml.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH = $$PWD/qml

# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH = $$PWD/qml

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

qml.qrc

<RCC>
    <qresource prefix="/">
        <file>main.qml</file>
        <file>qml/more/MyDeeperComponent.qml</file>
        <file>qml/more/MyDeeperComponentForm.ui.qml</file>
        <file>MySquare.qml</file>
        <file>MySquareForm.ui.qml</file>
    </qresource>
</RCC>

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

Window
{
  width: 640
  height: 480
  visible: true

  title: qsTr("Hello World")

  Column
  {
    MySquare {}

    Loader {
        source: "qrc:/qml/more/MyDeeperComponent.qml"
    }
  }
}

main.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;

  engine.addImportPath( "qrc:/qml" );

  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.load(url);

  return app.exec();
}

MySquare.qml

import QtQuick 2.4

MySquareForm {
}

MySquareForm.ui.qml

import QtQuick 2.4

Rectangle {
  width: 40
  height: 40

  color: "blue"
}

或者通过更改

编辑MyDeeperComponentForm.ui.qml
MySquare {}

Loader {
  source: "../../MySquare.qml"
}

或添加(如评论中所述)

import "../.."

但是请注意,从依赖关系的角度来看,您的用例看起来很奇怪...我想您已经熟悉 QML 中的不同导入机制,但无论如何添加 link 以供参考。