0

Similar to this question, I want to instantiate a sub-class of QObject, but I want to do this in a javascript function block itself.

I have a class:

class CoverageKind : public QObject {
  Q_OBJECT    
public:

  int64_t        id;
  QString        coverage_kind;

  CoverageKind(QObject * parent=nullptr);

  Q_PROPERTY(int64_t id MEMBER id NOTIFY id_changed)
  Q_PROPERTY(QString coverage_kind MEMBER coverage_kind NOTIFY coverage_kind_changed)

signals:
  void id_changed();
  void coverage_kind_changed();
};

This is registered with QML like:

qmlRegisterType<CoverageKind>("com.example.CoverageKind", 0, 1, "CoverageKind");

After importing com.example.CoverageKind, I can instantiate this QObject subclass like:

Item {
  CoverageKind {
    id: ck
    Component.onCompleted: {
      console.log('Created CoverageKind! ', ck);
    }
  }
}

Which prints:

Created CoverageKind!  CoverageKind(0x19b51b0)

However, if I do:

import com.example.CoverageKind 0.1;
Item {
  CoverageKind ck;
  Component.onCompleted: {
    ck = new CoverageKind();
  }
}

I get TypeError: Type error on the ck = new ... line.

I there an idiomatic way that can I instantiate a C++ QObject subclass from a QML javascript block?

I can do

var ck = Qt.createComponent("import com.example.CoverageKind 0.1; CoverageKind{}");

This feels really clunky. I could also create a factory function, but I was hoping to be able to create these objects inside of javascript more ergonomically.

Ross Rogers
  • 23,523
  • 27
  • 108
  • 164

2 Answers2

1

new does not exist in QML, and the closest thing to what you want is to create property of type CoverageKind that is null initially and in Component.onCompleted you will be assigned the value created with Qt.createQmlObject().

import QtQuick 2.0
import com.example.CoverageKind 0.1;

Item {
    id: parentItem
    property CoverageKind ck: null
    Component.onCompleted: {
        ck = Qt.createQmlObject('import com.example.CoverageKind 0.1; CoverageKind{}',
                                parentItem,
                                "dynamicSnippet1");
    }
}
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
1

Make your item into a component

Component {
  id: myComponent
  CoverageKind {}
}

Then anywhere you can do:

var ckobj = myComponent.createObject (/*...*/)

Now ckobj is a new instance

GrecKo
  • 6,615
  • 19
  • 23
mike510a
  • 2,102
  • 1
  • 11
  • 27