Qt 6 is a result of the conscious effort to make the framework more efficient and easy to use.
We try to maintain binary and source compatibility for all the public APIs in each release. But some changes were inevitable in an effort to make Qt a better framework.
In this topic we summarize those changes in Qt QML, and provide guidance to handle them.
In Qt 5, relative urls were often, albeit inconsistently, directly resolved, especially when assigned to an url property. In Qt 6 this is no longer the case.
If you had a QML file stored under "/home/qml/example.qml", and "example.qml" contained
property url imageFolder: "./images"
then the url property would store the URL "/home/qml/images". This made it impossible to use relative URLs in QML in this way, so in Qt 6, the URL stays relative, and only gets resolved when this is required (e.g. when it is
used as the source of an Image component). If you depend on the old behavior, you can use Qt.resolvedUrl
For example, if you have code like
property url imageFolder: "./images"
you can rewrite it as
property url imageFolder: Qt.resolvedUrl("./images")
Qt.resolvedUrl can be used in both Qt 5 and 6.
variant
properties, which have been marked as obsolete since Qt 5, are now treated in exactly the same way as var
properties. Code that relied on implicit string conversion triggered on assignment
to variant properties should be updated to explicitly create an object of the correct type.
For example, if you have code like
property variant myColor: "red"
you can rewrite it as
property variant myColor: Qt.color("red")
Implicit conversions were done for strings that could be parsed as
variant
still remains a deprecated keyword in Qt 6, though new code is strongly encouraged to use var
properties instead.
Note: If the type of the property is known not to change, use a property of the concrete type, instead of a var
property.
Note: These conversions were also applied to QVariant
properties of classes registered with the engine. As with variant
properties, code that relied on implicit string conversions need to
use the corresponding functions of the Qt object.
QQmlListProperty
's CountFunction
and AtFunction
have been changed to use qsizetype
instead of int
to align with the corresponding changes in Qt's
containers.
For example, if you have code like
int myCountFunction(QQmlListProperty<MyType> *); MyType *myAtFunction(QQmlListProperty<MyType> *, int); QQmlListProperty<MyType> myReadOnlyList(containingObject, container, &myCountFunction, &myAtFunction);
you can rewrite it as
qsizetype myCountFunction(QQmlListProperty<MyType> *); MyType *myAtFunction(QQmlListProperty<MyType> *, qsizetype); QQmlListProperty<MyType> myReadOnlyList(containingObject, container, &myCountFunction, &myAtFunction);
Code which needs to supports both Qt 5 and Qt 6 can either use a typedef which is int
in Qt 5 and qsizetype
in Qt 6, or use QList::size_type
, which already is such a type alias.
Various deprecated functions have been removed.
For example, if you have code like
QQmlListProperty<QObject>(owner, owner->objectList);
you can rewrite it as
QQmlListProperty<QObject>(owner, &owner->objectList);
qmlDebug
, qmlInfo
, qmlWarning
, qmlContext
and qmlEngine
used to exist both in the global namespace (or Qt namespace in namespaced builds), and
in the QtQml
namespace. These functions now exist only in the global namespace.
For example, if you have code like
QQmlEngine *engine = QtQml::qmlEngine(qmlObject);
you can rewrite it as
QQmlEngine *engine = qmlEngine(qmlObject);
qmlRegisterType
overload taking no arguments has been removed. Use qmlRegisterAnonymousType
instead, or switch to declarative type registration with QML_ANONYMOUS
.
For example, if you have code like
class AnonymousType : public QObject { // ... }; qmlRegisterType<AnonymousType>();
you can rewrite it as
class AnonymousType : public QObject { // ... }; qmlRegisterAnonymousType<AnonymousType>("MyModule", 1);
Or alternatively
class AnonymousType : public QObject { QML_ANONYMOUS // ... };
qmlRegisterExtendedType
and qmlRegisterInterface
which take no version argument have been removed. Use the overloads providing a version, or switch to declarative type
registration with QML_EXTENDED and QML_INTERFACE.
For example, if you have code like
struct GreetInterface { virtual ~GreetInterface(); virtual void greet(); }; Q_DECLARE_INTERFACE(GreetInterface, "org.hi.GreetInterface") qmlRegisterInterface<GreetInterface>("Greeter");
you can rewrite it as
struct GreetInterface { virtual ~GreetInterface(); virtual void greet(); }; Q_DECLARE_INTERFACE(GreetInterface, "org.hi.GreetInterface") qmlRegisterInterface<GreetInterface>("Greeter", 1);
Alternatively
struct GreetInterface { QML_INTERFACE(Greeter) virtual ~GreetInterface(); virtual void greet(); }; Q_DECLARE_INTERFACE(GreetInterface, "org.hi.GreetInterface")
Note: In new code, declarative type registration should be preferred.
QJSValue::engine
has been removed. If access to the engine is required, a reference to it must be stored instead.qmlAttachedPropertiesObjectById
and qmlAttachedPropertiesObject(int *, const QObject *, const QMetaObject *, bool)
have been removed. Use the qmlAttachedPropertiesObject(QObject *,
QQmlAttachedPropertiesFunc, bool)
overload of qmlAttachedPropertiesObject
instead.QJSEngine::installTranslatorFunctions
has been removed. QJSEngine::installExtensions
is available as a replacement.
For example, if you have code like
QJSEngine engine; engine.installTranslatorFunctions();
you can rewrite it as
QJSEngine engine; engine.installExtensions(QJSEngine::TranslationExtension);