Qt 如何将QML文件组织到嵌套文件夹中?
我有一个样本项目在 如果我的层次结构如下所示:Qt 如何将QML文件组织到嵌套文件夹中?,qt,qml,Qt,Qml,我有一个样本项目在 如果我的层次结构如下所示: $ tree qml_location/ qml_location/ ├── MyDeepComponent.qml ├── MyDeepComponentForm.ui.qml ├── main.cpp ├── main.qml ├── qml.qrc └── qml_location.pro import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.12
$ tree qml_location/
qml_location/
├── MyDeepComponent.qml
├── MyDeepComponentForm.ui.qml
├── main.cpp
├── main.qml
├── qml.qrc
└── qml_location.pro
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
{
MyDeepComponent {}
MyDeeperComponent {}
}
}
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")
property var componentNames: [ "qml/more/MyDeeperComponent.qml", "qml/MyDeepComponent.qml" ]
function generateObjects()
{
function generateOneObject( name )
{
var component
var componentObject
function finishCreation()
{
componentObject = component.createObject( contentColumn );
}
component = Qt.createComponent( `qrc:/${name}` )
if ( component.status === Component.Ready )
{
finishCreation()
}
else
{
component.statusChanged.connect( finishCreation );
}
}
for ( var index in componentNames )
{
generateOneObject( componentNames[ index ] )
}
}
Component.onCompleted: {
generateObjects()
}
Column
{
id: contentColumn
}
}
然后我可以编写main.qml
如下:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
MyDeepComponent {}
}
它会起作用的
但是,我希望将一些QML文件组织到文件夹层次结构中,而不是让它们都处于同一级别
例如,如果我移动到:
$ tree qml_location/
qml_location/
├── main.cpp
├── main.qml
├── qml
│ ├── MyDeepComponent.qml
│ ├── MyDeepComponentForm.ui.qml
│ └── more
│ ├── MyDeeperComponent.qml
│ └── MyDeeperComponentForm.ui.qml
├── qml.qrc
└── qml_location.pro
并且有一个main.qml
,看起来像:
$ tree qml_location/
qml_location/
├── MyDeepComponent.qml
├── MyDeepComponentForm.ui.qml
├── main.cpp
├── main.qml
├── qml.qrc
└── qml_location.pro
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
{
MyDeepComponent {}
MyDeeperComponent {}
}
}
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")
property var componentNames: [ "qml/more/MyDeeperComponent.qml", "qml/MyDeepComponent.qml" ]
function generateObjects()
{
function generateOneObject( name )
{
var component
var componentObject
function finishCreation()
{
componentObject = component.createObject( contentColumn );
}
component = Qt.createComponent( `qrc:/${name}` )
if ( component.status === Component.Ready )
{
finishCreation()
}
else
{
component.statusChanged.connect( finishCreation );
}
}
for ( var index in componentNames )
{
generateOneObject( componentNames[ index ] )
}
}
Component.onCompleted: {
generateObjects()
}
Column
{
id: contentColumn
}
}
Qt Creator告诉我MyDeepComponent和MyDeeperComponent是未知的
当我尝试运行时,我得到一个错误:MyDeepComponent不是一个类型
我能做些什么才能让它起作用
需要注意的是,我不想在main.qml的顶部放置特殊或额外的导入。这还可能吗
qml.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>qml/MyDeepComponent.qml</file>
<file>qml/MyDeepComponentForm.ui.qml</file>
<file>qml/more/MyDeeperComponent.qml</file>
<file>qml/more/MyDeeperComponentForm.ui.qml</file>
</qresource>
</RCC>
编辑:我正在阅读你的问题部分,其中你表示不希望在顶部导入。我认为这是不可能的,如果不在主文件夹(对于要创建的每个文件夹)中抛出一堆
addImportPath
,或者大量修改qrc别名。把剩下的答案留给未来的访客,或者如果你改变主意,留给未来的访客;-)
您可以使用
qmldir
文件使它们在所选命名空间中可用。但有一点学习曲线。qmldir
文件必须位于类似名称空间的文件夹中
例如,如果要使用MyApplication
作为名称空间,则必须将qmldir
文件放在文件夹“MyApplication”(在qml导入路径内)中。如果希望MyOrg.application1
作为名称空间,则必须将qmldir
放在“MyOrg/application1”中
根据你的情况,我选择第一种选择。我将为可导入的qml文件创建一个单独的qrc文件,如果您想轻松地将所有qml文件放在“qml”文件夹中,也需要该文件:
您可以看到我使用了前缀,这样文件就不必移动。如果您想使用该应用程序达到更高的境界,并且想要一个
MyApplication 2.0
名称空间,您可以使用前缀/qml/MyApplication.2
您可以执行以下操作:
module MyApplication
MyDeepComponent 1.0 MyDeepComponent.qml
MyDeeperComponent 1.0 more/MyDeeperComponent.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
{
Loader {
source: "qrc:/qml/MyDeepComponent.qml"
}
Loader {
source: "qrc:/qml/more/MyDeeperComponent.qml"
}
}
}
虽然我不太清楚你为什么要这么做。可能有助于描述您试图解决的问题?
createObject可用于将组件直接加载到列中
main.qml看起来像:
$ tree qml_location/
qml_location/
├── MyDeepComponent.qml
├── MyDeepComponentForm.ui.qml
├── main.cpp
├── main.qml
├── qml.qrc
└── qml_location.pro
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
{
MyDeepComponent {}
MyDeeperComponent {}
}
}
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")
property var componentNames: [ "qml/more/MyDeeperComponent.qml", "qml/MyDeepComponent.qml" ]
function generateObjects()
{
function generateOneObject( name )
{
var component
var componentObject
function finishCreation()
{
componentObject = component.createObject( contentColumn );
}
component = Qt.createComponent( `qrc:/${name}` )
if ( component.status === Component.Ready )
{
finishCreation()
}
else
{
component.statusChanged.connect( finishCreation );
}
}
for ( var index in componentNames )
{
generateOneObject( componentNames[ index ] )
}
}
Component.onCompleted: {
generateObjects()
}
Column
{
id: contentColumn
}
}
这个答案不满足不导入的要求,但无论如何值得一提的是,它可以通过main.qml顶部的几个导入来解决
另一种解决方案是将main.qml移动到qml文件夹中。这允许main.qml查找MyDeepComponent,因为它们是同级。要查找MyDeeperComponent,main.qml可以导入“more”目录 此解决方案在分支中表示 目录结构
$ tree qml_location/
qml_location/
├── main.cpp
├── qml
│ ├── MyDeepComponent.qml
│ ├── MyDeepComponentForm.ui.qml
│ ├── main.qml
│ └── more
│ ├── MyDeeperComponent.qml
│ └── MyDeeperComponentForm.ui.qml
├── qml.qrc
├── qml_location.pro
└── qml_location.pro.user
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;
const QUrl url(QStringLiteral("qrc:/qml/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();
}
添加
import“qml”
和import“qml/more”
@eyllanesc,OP说他不想使用import
。不过,我不确定原因是什么@James Hudson,我还没有尝试过这个方法,但是如果在.qrc文件中使用别名,它可能会起作用。可以使用别名,但在QtCreator中,它们看起来都在同一个文件夹中,因此唯一的好处是在磁盘/git上排序,而不是在IDE中排序@JamesHudson为什么要求不导入?我可以更具体地说,我不希望导入直接导入MyDeepComponent。原因与。。。我将需要动态加载qml文件并减少代码维护,我不希望在需要时添加导入语句。然而,正如@eyllanesc指出的,看起来导入“qml”等是一个可行的选择。我想尝试让这个解决方案工作,但目前我失败了。我有一个名为“qmldir_solution”的分支,在该分支上尝试实现您的建议。尝试了您在上建议的变体,但不幸的是,它也不起作用。您仍然需要addImportPath(:/qml:);
。我扔掉了我的更改,在垃圾桶里找不到它们,否则我会为您上传它们。我想我的问题是我很难理解和实现您的答案。如果您能提供更多细节或解释我哪里出错,我会感兴趣。我曾尝试添加导入,但没有成功lp.我确实找到了问题的解决方案。正如您在上文中所回避的那样,为了使其正常工作,qmldir和qml文件应该位于名为Components的文件夹中,以了解qmldir如何定义组件。Qt Creator很高兴,代码运行正常。我已经更新了项目,原因与…有关。我将尝试您的解决方案。Wha我将要做的是基于QDirIterator或FolderListModel动态生成这些加载程序对象,以在资源中找到一组QML文件,这些文件定义了需要插入的组件。组件的列表很大,并且会不断增加。我不确定这是否是讨论我的用例的合适论坛。我们可以移动它到或其他地方。为什么不使用该解决方案?动态加载并创建组件?这是一个好问题。在另一个上下文中,我尝试了它,但它不起作用。在这个上下文中尝试了它,但它起作用了。我需要找出原因。无论如何,我尝试了你的加载程序解决方案,它起作用了。