Implementing proper C++ model for QML
-
I have some experience with Qt Widgets, but rather new to Qt Quick. I`m trying to implement C++ model with QML frontend.
My model inherits from QAbstractListModel like this:
class MainModel : public QAbstractListModel {...}
Then I implemented Backend class which provides access to model for QML:
Backend { ... Q_PROPERTY(MainModel* main_model READ getMainModel CONSTANT) ... Backend() { ... main_model = new MainModel(this); ... } ... }
And my main.cpp looks like:
... Backend backend; engine.rootContext()->setContextProperty(QStringLiteral("backend"), &backend); ... return app.exec();
Everything seems to work fine, but when I exit my application it crushes when ~Backend() is called:
qrc:/ui/Viewer.qml:21: TypeError: Cannot read property 'main_model' of null
The "dirty" way to get rid of this error is create Backend as new Backend() and never call a destructor. What am I missing here?
upd:
forgot about QML part:
ListView { ... model: backend.main_model ...
-
Your code looks OK and should work.
A few hints:
- make sure you set rootContext property before you load your main QML file
- make sure both
Backend
andMainModel
haveQ_OBJECT
macro and that they initialize parentQObject
in constructors
-
Ah sorry I didn't notice the problem is when closing the application. In this case, the solution should be pretty simple: change Backend into a pointer and let QML engine manage it's lifetime:
auto backend = new Backend(&engine); engine.rootContext()->setContextProperty(QStringLiteral("backend"), backend);
Thanks to QObject parent-child system, your backend will be deleted auotmatically when
engine
will be deleted. And doing it this way ensures that deletion happens in correct order.This is some bug / change in Qt 6. Same code as you have now would work without issues in Qt 5.
-
@sierdzio It looks like I have a problem with QQmlApplicationEngine itself. If I create it on stack or with smart pointer it crash instead of exit. Insanity. Well, thanks again. At least I was able to localize a problem. Though I still don`t understand why it is happening.
upd:
Well, mystery solved. Finally. It was QQuickImageProvider! I suppose QQmlApplicationEngine takes ownership over it as soon as it is passed (or at least tryes to delete it in destructor). Also here: https://forum.qt.io/topic/91895/qml-imageprovider-crashes. Though error messages were really confusing. This was the last place to check.
upd2:
And also as @sierdzio said
auto backend = new Backend(&engine);
Is also important. It should not be on stack.
-
-
@bidjiz said in Implementing proper C++ model for QML:
Is also important. It should not be on stack.
It can be on the stack, it just has to be constructed before the engine.