为什么我不能使用我的 QML 单例模块?
Why can I not use my QML singleton module?
我在 https://github.com/jh3010-qt-questions/font_test
有一个简单的测试项目
构建时出现错误:
qrc:/main.qml:5 module "Fonts" is not installed
我的目录结构如下:
font_test
├── assets
│ └── Fonts
│ ├── Art Brewery.ttf
│ ├── Fonts.qml
│ ├── Roboto-Light.ttf
│ ├── Roboto-Medium.ttf
│ ├── Roboto-Regular.ttf
│ └── qmldir
├── font_test.pro
├── font_test.pro.user
├── main.cpp
├── main.qml
└── qml.qrc
我的 qml.qrc 文件是:
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
<qresource prefix="/Fonts">
<file alias="Art Brewery.ttf">assets/Fonts/Art Brewery.ttf</file>
<file alias="Roboto-Light.ttf">assets/Fonts/Roboto-Light.ttf</file>
<file alias="Roboto-Medium.ttf">assets/Fonts/Roboto-Medium.ttf</file>
<file alias="Roboto-Regular.ttf">assets/Fonts/Roboto-Regular.ttf</file>
</qresource>
</RCC>
我的project file是:
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/assets
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES += \
assets/Fonts/Fonts.qml \
assets/Fonts/qmldir
我的 Fonts.qml 文件是:
pragma Singleton
import QtQuick 2.12
Item
{
readonly property FontLoader artBrewery: FontLoader { source: "qrc:/Fonts/Art Brewery.ttf" }
readonly property FontLoader robotoLight: FontLoader { source: "qrc:/Fonts/Roboto-Light.ttf" }
readonly property FontLoader robotoMedium: FontLoader { source: "qrc:/Fonts/Roboto-Medium.ttf" }
readonly property FontLoader robotoRegular: FontLoader { source: "qrc:/Fonts/Roboto-Regular.ttf" }
}
我在 assets/fonts 文件夹中的 qmldir 是:
singleton Fonts 1.0 Fonts.qml
我尝试使用main.qml
中的字体
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import Fonts 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Column
{
spacing: 8
anchors.fill: parent
anchors.margins: 8
Label
{
text: "DEFAULT: Pack my box with five dozen liquor jugs"
}
Label
{
text: "ART BREWERY: Pack my box with five dozen liquor jugs"
font.family: Fonts.artBrewery.name
font.pixelSize: 36
}
Label
{
text: "ROBOTO: Pack my box with five dozen liquor jugs"
}
}
}
在我将 QML_IMPORT_PATH = $$PWD/assets
添加到我的项目文件之前,Qt Creator 会抱怨 import Fonts 1.0
。需要这样做有意义吗?
我想知道 assets/fonts/qmldir
是否属于 DISTFILES
...?
我不确定需要更改什么,所以 main.qml 中的 font.family: Fonts.artBrewery.name
会起作用。
如所述here,该模块必须在 QML 引擎的导入路径中可用:
To define a module, a developer should gather together the various QML documents, JavaScript resources and C++ plugins which belong in the module into a single directory, and write an appropriate module definition qmldir file which should also be placed into the directory. The directory can then be installed into the QML import path as a module.
您可以通过使用包含 qmldir
的目录的父目录的路径调用 addImportPath() 来完成此操作。当您使用
导入模块时
import Fonts 1.0
QML 引擎在每个导入路径中查找名为 Fonts
的目录,如果找到,则查找 qmldir
文件。由于您在 QRC 文件中使用了前缀,因此 qmldir
文件的最终路径是 :/Fonts/qmldir
。 Fonts
的父目录(包含qmldir
的目录)是根资源目录:/
,所以:
diff --git a/main.cpp b/main.cpp
index 3d80569..de4efb7 100644
--- a/main.cpp
+++ b/main.cpp
@@ -10,6 +10,7 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
+ engine.addImportPath(":/");
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
您还需要确保您的模块使用的所有文件都可以作为资源使用。这意味着添加以下文件:
diff --git a/qml.qrc b/qml.qrc
index f212706..40cb8dc 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -3,6 +3,8 @@
<file>main.qml</file>
</qresource>
<qresource prefix="/Fonts">
+ <file alias="qmldir">assets/Fonts/qmldir</file>
+ <file alias="Fonts.qml">assets/Fonts/Fonts.qml</file>
<file alias="Art Brewery.ttf">assets/Fonts/Art Brewery.ttf</file>
<file alias="Roboto-Light.ttf">assets/Fonts/Roboto-Light.ttf</file>
<file alias="Roboto-Medium.ttf">assets/Fonts/Roboto-Medium.ttf</file>
几分钟后我看到另一个答案打败了我。那好吧。我会 post 我的以防万一。
如何通过目录导入解决问题:
将丢失的文件添加到 qml.qrc
文件中的资源列表:
<qresource prefix="/Fonts">
...........
<file alias="Fonts.qml">assets/Fonts/Fonts.qml</file>
<file alias="qmldir">assets/Fonts/qmldir</file>
请注意alias
es,否则路径会不同
如果您不将文件添加到资源中,它们将不会通过 qrc://
可见,并且它们也不会包含在您编译的应用程序中,即您的代码只会 运行在您的计算机上,除非您使用应用程序手动安装丢失的文件
从 main.qml
移除模块导入:
//import Fonts 1.0
如果您通过 qmldir
文件
创建单例,则不需要(也不会起作用)
导入不会工作,因为 Qt 不会在 qrc://
路径中寻找模块,除非您在 C++ 代码中明确指定 - 请参阅其他答案了解如何做到这一点
而是在 main.qml
的顶部添加一个 directory import:
import "qrc:/Fonts/"
这会导入 qmldir
file,它会按照您指定的方式从文件 Fonts.qml
创建一个名为 Fonts
的单例
请注意,虽然它在目录中导入 qmldir
和 *.qml
files,但它不会告诉 Qt 从同一目录加载 modules。
我还必须将 QT += qml
添加到 font_test.pro
,但如果它完全编译的话,您的 Qt/QML 版本可能不需要它
像您已经在尝试的那样使用您的单例:Fonts.artBrewery.name
参考资料
有关详细信息,请参阅 Qt 文档:
我在 https://github.com/jh3010-qt-questions/font_test
有一个简单的测试项目构建时出现错误:
qrc:/main.qml:5 module "Fonts" is not installed
我的目录结构如下:
font_test
├── assets
│ └── Fonts
│ ├── Art Brewery.ttf
│ ├── Fonts.qml
│ ├── Roboto-Light.ttf
│ ├── Roboto-Medium.ttf
│ ├── Roboto-Regular.ttf
│ └── qmldir
├── font_test.pro
├── font_test.pro.user
├── main.cpp
├── main.qml
└── qml.qrc
我的 qml.qrc 文件是:
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
<qresource prefix="/Fonts">
<file alias="Art Brewery.ttf">assets/Fonts/Art Brewery.ttf</file>
<file alias="Roboto-Light.ttf">assets/Fonts/Roboto-Light.ttf</file>
<file alias="Roboto-Medium.ttf">assets/Fonts/Roboto-Medium.ttf</file>
<file alias="Roboto-Regular.ttf">assets/Fonts/Roboto-Regular.ttf</file>
</qresource>
</RCC>
我的project file是:
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/assets
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES += \
assets/Fonts/Fonts.qml \
assets/Fonts/qmldir
我的 Fonts.qml 文件是:
pragma Singleton
import QtQuick 2.12
Item
{
readonly property FontLoader artBrewery: FontLoader { source: "qrc:/Fonts/Art Brewery.ttf" }
readonly property FontLoader robotoLight: FontLoader { source: "qrc:/Fonts/Roboto-Light.ttf" }
readonly property FontLoader robotoMedium: FontLoader { source: "qrc:/Fonts/Roboto-Medium.ttf" }
readonly property FontLoader robotoRegular: FontLoader { source: "qrc:/Fonts/Roboto-Regular.ttf" }
}
我在 assets/fonts 文件夹中的 qmldir 是:
singleton Fonts 1.0 Fonts.qml
我尝试使用main.qml
中的字体import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import Fonts 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Column
{
spacing: 8
anchors.fill: parent
anchors.margins: 8
Label
{
text: "DEFAULT: Pack my box with five dozen liquor jugs"
}
Label
{
text: "ART BREWERY: Pack my box with five dozen liquor jugs"
font.family: Fonts.artBrewery.name
font.pixelSize: 36
}
Label
{
text: "ROBOTO: Pack my box with five dozen liquor jugs"
}
}
}
在我将 QML_IMPORT_PATH = $$PWD/assets
添加到我的项目文件之前,Qt Creator 会抱怨 import Fonts 1.0
。需要这样做有意义吗?
我想知道 assets/fonts/qmldir
是否属于 DISTFILES
...?
我不确定需要更改什么,所以 main.qml 中的 font.family: Fonts.artBrewery.name
会起作用。
如所述here,该模块必须在 QML 引擎的导入路径中可用:
To define a module, a developer should gather together the various QML documents, JavaScript resources and C++ plugins which belong in the module into a single directory, and write an appropriate module definition qmldir file which should also be placed into the directory. The directory can then be installed into the QML import path as a module.
您可以通过使用包含 qmldir
的目录的父目录的路径调用 addImportPath() 来完成此操作。当您使用
import Fonts 1.0
QML 引擎在每个导入路径中查找名为 Fonts
的目录,如果找到,则查找 qmldir
文件。由于您在 QRC 文件中使用了前缀,因此 qmldir
文件的最终路径是 :/Fonts/qmldir
。 Fonts
的父目录(包含qmldir
的目录)是根资源目录:/
,所以:
diff --git a/main.cpp b/main.cpp
index 3d80569..de4efb7 100644
--- a/main.cpp
+++ b/main.cpp
@@ -10,6 +10,7 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
+ engine.addImportPath(":/");
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
您还需要确保您的模块使用的所有文件都可以作为资源使用。这意味着添加以下文件:
diff --git a/qml.qrc b/qml.qrc
index f212706..40cb8dc 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -3,6 +3,8 @@
<file>main.qml</file>
</qresource>
<qresource prefix="/Fonts">
+ <file alias="qmldir">assets/Fonts/qmldir</file>
+ <file alias="Fonts.qml">assets/Fonts/Fonts.qml</file>
<file alias="Art Brewery.ttf">assets/Fonts/Art Brewery.ttf</file>
<file alias="Roboto-Light.ttf">assets/Fonts/Roboto-Light.ttf</file>
<file alias="Roboto-Medium.ttf">assets/Fonts/Roboto-Medium.ttf</file>
几分钟后我看到另一个答案打败了我。那好吧。我会 post 我的以防万一。
如何通过目录导入解决问题:
将丢失的文件添加到
qml.qrc
文件中的资源列表:<qresource prefix="/Fonts"> ........... <file alias="Fonts.qml">assets/Fonts/Fonts.qml</file> <file alias="qmldir">assets/Fonts/qmldir</file>
请注意alias
es,否则路径会不同
如果您不将文件添加到资源中,它们将不会通过 qrc://
可见,并且它们也不会包含在您编译的应用程序中,即您的代码只会 运行在您的计算机上,除非您使用应用程序手动安装丢失的文件
从
main.qml
移除模块导入://import Fonts 1.0
如果您通过 qmldir
文件
导入不会工作,因为 Qt 不会在 qrc://
路径中寻找模块,除非您在 C++ 代码中明确指定 - 请参阅其他答案了解如何做到这一点
而是在
main.qml
的顶部添加一个 directory import:import "qrc:/Fonts/"
这会导入 qmldir
file,它会按照您指定的方式从文件 Fonts.qml
创建一个名为 Fonts
的单例
请注意,虽然它在目录中导入 qmldir
和 *.qml
files,但它不会告诉 Qt 从同一目录加载 modules。
我还必须将
QT += qml
添加到font_test.pro
,但如果它完全编译的话,您的 Qt/QML 版本可能不需要它像您已经在尝试的那样使用您的单例:
Fonts.artBrewery.name
参考资料
有关详细信息,请参阅 Qt 文档: