Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Implementing proper C++ model for QML
Forum Updated to NodeBB v4.3 + New Features

Implementing proper C++ model for QML

Scheduled Pinned Locked Moved Solved QML and Qt Quick
6 Posts 3 Posters 519 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    bidjiz
    wrote on last edited by bidjiz
    #1

    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
    
    ...
    
    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      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 and MainModel have Q_OBJECT macro and that they initialize parent QObject in constructors

      (Z(:^

      B 1 Reply Last reply
      0
      • sierdzioS sierdzio

        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 and MainModel have Q_OBJECT macro and that they initialize parent QObject in constructors
        B Offline
        B Offline
        bidjiz
        wrote on last edited by
        #3

        @sierdzio Thank you for your answer. Both your hints are implemented. In fact everything works, except the destructor part. I've started to think that the actual problem is somewhere else and I just can`t catch it.

        1 Reply Last reply
        0
        • sierdzioS Offline
          sierdzioS Offline
          sierdzio
          Moderators
          wrote on last edited by
          #4

          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.

          (Z(:^

          B 1 Reply Last reply
          1
          • sierdzioS sierdzio

            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.

            B Offline
            B Offline
            bidjiz
            wrote on last edited by bidjiz
            #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.

            GrecKoG 1 Reply Last reply
            1
            • B bidjiz has marked this topic as solved on
            • B bidjiz

              @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.

              GrecKoG Offline
              GrecKoG Offline
              GrecKo
              Qt Champions 2018
              wrote on last edited by
              #6

              @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.

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved