Search code examples
c++qtqmlqobject

Can't access C++ QObject subclass methods from QML


Yesterday I was asked to recreate a regular QT form using QML (which was my first attempt ever using QLM). Everything was going well until I tried using c++ methods in the QML. This is obviously not the original code, but the scenario looks something like this:

I have a super class deriving from QObject, with some properties, methods and even virtual methods:

class SuperClass : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString someProperty READ someProperty WRITE setSomeProperty)

protected:
    QString m_someProperty;

public:
    QString someProperty(void){return m_someProperty;}  //get method
    void setSomeProperty(QString newValue){m_someProperty = newValue;}  //set method
    Q_INVOKABLE virtual QString printSomething(void) = 0;
}

And then I have a class deriving from the SuperClass (like a specialization) with some more specific properties and methods and of course the virtual methods implementations and stuff:

class DerivedClass : public SuperClass {
Q_PROPERTY(QString someSpecificProperty READ someSpecificProperty WRITE setSomeSpecificProperty)

private:
    QString m_someSpecificProperty;

public:
    QString specificProperty(void){return m_someSpecificProperty;}  //get method
    void someSpecificProperty(QString newValue){m_someSpecificProperty = newValue;}  //set method
    QString printSomething(void){return QString("Something!");}  //SuperClass virtual method
    Q_INVOKABLE QString printSomethingSpecific(void){return QString("Something Specific!");}
}

OK, this is it! Now assuming that DerivedClass is instantiated and added to the QML context properly under the name of "DrvClass" for example and that I have some QML control like a TextField which has a 'text:' property:

text: DrvClass.someProperty

using MasterClass' properties, it works just fine.

text: DrvClass.printSomething()

even using virtual methods from MasterClass' which are implemented in the derived class works fine. but...

text: DrvClass.someSpecificProperty

doesn't work and I get something like "Unable to assign [undefined] to QString"

text: DrvClass.printSomethingSpecific()

also doesn't work! "TypeError: Property 'printSomethingSpecific' of object SuperClass() is not a function" And the weird part is that it says that it's not a function from the SuperClass, being the instantiated class the Derived one!

I've looked for similar errors, but most of the time is from people who just forgot to include the Q_OBJECT macro... Mine's there for sure! It seems that QML doesn't like much classes deriving from other classes that derive from QObjects :-/ Probably something to do with the meta-object compiler who only looks for invokable methods where it finds the Q_OBJECT macro and not on it's subclasses!

So what you guys think the solution for this might be? I could just add the Q_OBJECT macro to the DerivedClasses instead of the SuperClass, but I really need the SuperClass to be a QObject because of signals and stuff! So is there some other macro I have to add to the DerivedClass for the moc to 'see' it? Or is this just the fruit of inexperience and I'm doing a dumb mistake somewhere?


Solution

  • DerivedClass is missing Q_OBJECT macro (it is not inherited!).

    Then simply run qmake again on your project & compile: it should work.