Qt QML 的更改
Qt 6 是经过有意识的努力,使框架更加高效和易于使用的结果。
我们试图在每次发布中都维护所有公共 API 的二进制和源代码兼容性。但为了使 Qt 成为更好的框架,一些更改不可避免。
在本主题中,我们对 Qt QML 中的这些更改进行了总结,并提供了相应的处理指南。
QML 语言
URL 解析
在 Qt 5 中,相对 URL 通常(尽管不一致)直接解析,尤其是在赋值给 URL 属性时。在 Qt 6 中,情况已经不再是这样了。
如果您的 QML 文件存储在 "/home/qml/example.qml",而 "example.qml" 包含
property url imageFolder: "./images"
那么 URL 属性将存储 URL "/home/qml/images"。这使得无法以这种方式在 QML 中使用相对 URL,因此,在 Qt 6 中,URL 保持相对,只有在该 URL 不得不使用时(例如,作为 Image 组件的源)才会被解析。如果依赖旧的操作,可以使用 Qt.resolvedUrl
例如,如果您的代码如下所示
property url imageFolder: "./images"
您可以将其重写为
property url imageFolder: Qt.resolvedUrl("./images")
Qt.resolvedUrl 可用于 Qt 5 和 6。
可变属性
自 Qt 5 被标记为废弃的 variant
属性,现在被完全等同于 var
属性处理。依赖于将属性赋值给 variant 属性时触发的隐式字符串转换的代码应更新为显式创建正确类型的对象。
例如,如果您的代码如下所示
property variant myColor: "red"
您可以将其重写为
property variant myColor: Qt.color("red")
对于可解析为
- 颜色(使用 Qt.color),
- 日期(使用 Date 对象),
- 矩形(使用 Qt.rect),和
- 尺寸(使用 Qt.size)的字符串
variant
在 Qt 6 中仍然是一个废弃的关键字。尽管如此,强烈建议新代码使用 var
属性。
注意:如果属性的已知类型不会发生变化,请使用具体类型的属性,而不是 var
属性。
注意:这些转换也应用于与引擎注册的类的 QVariant
属性。与 variant
属性一样,依赖隐式字符串转换的代码需要使用 Qt 对象的相关函数。
源不兼容的 API 更改
改变的 API
QQmlListProperty
的 CountFunction
和 AtFunction
已被更改为使用 qsizetype
而不是 int
,以与 Qt 容器中的更改保持一致。
例如,如果您的代码如下所示
int myCountFunction(QQmlListProperty<MyType> *); MyType *myAtFunction(QQmlListProperty<MyType> *, int); QQmlListProperty<MyType> myReadOnlyList(containingObject, container, &myCountFunction, &myAtFunction);
您可以将其重写为
qsizetype myCountFunction(QQmlListProperty<MyType> *); MyType *myAtFunction(QQmlListProperty<MyType> *, qsizetype); QQmlListProperty<MyType> myReadOnlyList(containingObject, container, &myCountFunction, &myAtFunction);
既需要支持 Qt 5 又需要支持 Qt 6 的代码可以采用一个 `typedef`,它在 Qt 5 中是 int
,在 Qt 6 中是 qsizetype
,或者使用 QList::size_type
,它已经是此类别名。
移除的 API
已移除各种弃用的函数。
- 移除了接收引用的 QQmlListProperty 构造函数。
例如,如果您的代码如下所示
QQmlListProperty<QObject>(owner, owner->objectList);
您可以将其重写为
QQmlListProperty<QObject>(owner, &owner->objectList);
- 函数
qmlDebug
、qmlInfo
、qmlWarning
、qmlContext
和qmlEngine
以前既存在于全局命名空间(或在有命名空间的构建中存在 Qt 命名空间),也存在于QtQml
命名空间中。这些函数现在仅存在于全局命名空间中。例如,如果您的代码如下所示
QQmlEngine *engine = QtQml::qmlEngine(qmlObject);
您可以将其重写为
QQmlEngine *engine = qmlEngine(qmlObject);
- 移除了不带参数的
qmlRegisterType
重载。请使用qmlRegisterAnonymousType
,或者切换到使用QML_ANONYMOUS
的声明性类型注册。例如,如果您的代码如下所示
class AnonymousType : public QObject { // ... }; qmlRegisterType<AnonymousType>();
您可以将其重写为
class AnonymousType : public QObject { // ... }; qmlRegisterAnonymousType<AnonymousType>("MyModule", 1);
或者另外
class AnonymousType : public QObject { QML_ANONYMOUS // ... };
- 移除了不带版本参数的
qmlRegisterExtendedType
和qmlRegisterInterface
重载。请使用提供版本的重载,或者切换到使用 QML_EXTENDED 和 QML_INTERFACE 的声明性类型注册。例如,如果您的代码如下所示
struct GreetInterface { virtual ~GreetInterface(); virtual void greet(); }; Q_DECLARE_INTERFACE(GreetInterface, "org.hi.GreetInterface") qmlRegisterInterface<GreetInterface>("Greeter");
您可以将其重写为
struct GreetInterface { virtual ~GreetInterface(); virtual void greet(); }; Q_DECLARE_INTERFACE(GreetInterface, "org.hi.GreetInterface") qmlRegisterInterface<GreetInterface>("Greeter", 1);
或者
struct GreetInterface { QML_INTERFACE(Greeter) virtual ~GreetInterface(); virtual void greet(); }; Q_DECLARE_INTERFACE(GreetInterface, "org.hi.GreetInterface")
注意:在新的代码中,应该优先使用声明性类型注册。
- 已移除函数
QJSValue::engine
。如果需要访问引擎,必须存储对其的引用。 - 已移除
qmlAttachedPropertiesObjectById
和qmlAttachedPropertiesObject(int *, const QObject *, const QMetaObject *, bool)
。请使用qmlAttachedPropertiesObject
的qmlAttachedPropertiesObject(QObject *, QQmlAttachedPropertiesFunc, bool)
重载。 - 已移除
QJSEngine::installTranslatorFunctions
。可以使用QJSEngine::installExtensions
替代。例如,如果您的代码如下所示
QJSEngine engine; engine.installTranslatorFunctions();
您可以将其重写为
© 2024 Qt 公司。此处包含的文档贡献享有其各自的版权。提供的文档受 GNU自由文档许可协议版本1.3 的许可,由自由软件基金会发布。Qt 及其相关标志是芬兰及/或全球其他地区 Qt 公司的商标。所有其他商标归其各自拥有者所有。