首先應了解C++類的知識, 環境變量的概念和一點CMake和Javascript語法, 否則下面的解釋可能有些難懂
Import語句, 共3種
1.import <ModuleIdentifier> [<Version.Number>] [as <Qualifier>]
例:import QtQuick 2.10 as Quick
這里QtQuick 2.10是一個模塊
(是一個類與頭文件的組合, 后面會討論)
,Quick叫做namespace qualifier,用來引用QtQuick 2.10
還可以(這里“textwidgets"看起來應該是一個文件):
import "../textwidgets" as MyModule
2.Directory Imports(也可以導目錄)
import "<DirectoryPath>" [as <Qualifier>]
3.JavaScript Resource Imports(javascript文件)
import "<JavaScriptFile>" as <Identifier>
上面例子中直接導入文件,那么這些文件在哪個目錄呢?
根據幫助文檔: QML Import Path
When an identified module is imported, the QML engine searches the import path for a matching module.
This import path, as returned by QQmlEngine::importPathList(), defines the default locations to be searched by the engine. By default, this list contains:
包括4種情況:
- The directory of the current file
- The location specified by QLibraryInfo::QmlImportsPath
- Paths specified by the QML_IMPORT_PATH environment variable
- The qrc:/qt-project.org/imports path inside the resources.
當標識模塊被導入(讀取import語句)時,QML引擎會查找匹配的 import路徑。
這些import路徑可通過QQmlEngine::importPathList()方法返回,默認情況下包括:
- 當前路徑;
- QLibraryInfo::QmlImportsPath指定的路徑;
- QML_IMPORT_PATH環境變量指定的路徑;
- 資源文件中指定的路徑:qrc:/qt-project.org/imports
Additional import paths can be added through QQmlEngine::addImportPath() or the QML_IMPORT_PATH environment variable. When running the qml tool, you can also use the -I option to add an import path.
可通過QQmlEngine::addImportPath()方法或QML_IMPORT_PATH環境變量添加路徑。當使用qml工具時也可通過 -I 參數添加一個import路徑。
查詢Qt Assistant得到,QQmlEngine::importPathList()的解釋,與上面4點是一致的:
QStringList QQmlEngine::importPathList() const
Returns the list of directories where the engine searches for installed modules in a URL-based directory structure.
For example, if /opt/MyApp/lib/imports is in the path, then QML that imports com.mycompany.Feature will cause the QQmlEngine to look in /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components provided by that module. A qmldir file is required for defining the type version mapping and possibly QML extensions plugins.
By default, the list contains the directory of the application executable, paths specified in the QML_IMPORT_PATH environment variable, and the builtin QmlImportsPath from QLibraryInfo.
You can specify multiple import paths in the QML_IMPORT_PATH environment variable by joining them using the path separator. On Windows the path separator is a semicolon (;), on other platforms it is a colon (:). This means that you cannot specify resource paths or URLs in QML_IMPORT_PATH, as they contain colons themselves. However, you can add resource paths and URLs by calling QQmlEngine::addImportPath() programatically.
路徑的問題解決了,那么如何將C++類定義為一個QML對象呢?
參考官方例子:QML 引用C++類實例:https://code.qt.io/cgit/qt/qtdeclarative.git/tree/examples/qml/referenceexamples/adding?h=6.2
首先你應了解C++類的知識,這里定義了一個person類:
#include "person.h"
// ![0]
QString Person::name() const { return m_name; }
void Person::setName(const QString &n) { m_name = n; } ……
然后是頭文件,這里的"Q_OBJECT, Q_PROPERTY..."需要一些Qt知識:
#ifndef PERSON_H #define PERSON_H #include <QObject> #include <QtQml/qqml.h> //![0] class Person : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName) Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize) QML_ELEMENT // 定義為QML元素 public: using QObject::QObject; QString name() const; void setName(const QString &); int shoeSize() const; void setShoeSize(int); private: QString m_name; int m_shoeSize = 0; }; //![0] #endif // PERSON_H
根據官方文檔:
C++ types are declared using the QML_ELEMENT and QML_NAMED_ELEMENT() macros and registered via the build system using QML_IMPORT_NAME and QML_IMPORT_MAJOR_VERSION. The import name and version given this way form a module that can be imported to access the types.
This is most common in client applications which define their own QML object types in C++.
這里注意QML_ELEMENT, 它指明這個頭文件對應的類是一個QML元素。根據幫助文檔:原文如下:
QML_ELEMENT:Declares the enclosing type or namespace to be available in QML, using its class or namespace name as the QML element name.
這里說明類名就是QML元素的名稱。
NOTE: When classes have the same name but are located in different namespaces using QML_ELEMENT on both of them will cause a conflict. Make sure to use QML_NAMED_ELEMENT() for one of them instead.
如果有多個相同名稱的類(處於不同命名空間),則使用QML_NAMED_ELEMENT() 宏來區分不同命名空間的類。
接下來在qml文件中引用它。
准備好了類,說明元素名已經確定了,import后面的模塊如何確定呢?比如:
import People 1.0
Person { name: "Bob Jones" shoeSize: 12 }
import
這里會報錯,說明找不到People這個模塊:
這就需要使用構建工具
在CMake中加入:
qt_add_qml_module(adding // 添加目標--工程名 URI People // 類名 VERSION 1.0 QML_FILES example.qml NO_RESOURCE_TARGET_PATH )
編譯一次就沒有問題了。
原理:
https://doc.qt.io/qt-6/qtqml-syntax-imports.html
QML 引用C++類實例:https://code.qt.io/cgit/qt/qtdeclarative.git/tree/examples/qml/referenceexamples/adding?h=6.2
