1
votes

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?

1
You should use Q_OBJECT macro in every QObject subclass which use properties or invokable. By the way, is your private inheritance conscious? - epsilon
No, actually a typo :-/ I tried adding adding Q_OBJECT on the derived class before, but it complains about something on compile time... I don't remember what it was but I think it was about the virtual table Yep, undefined reference to 'vtable' int the DerivedClass - RuiDo
How have you done the binding of the class to the QMContext, via setContextProperty? And which instance was binded to the QML engine,m the derived one or the base class? HAve you tired to use the derived one? - KimKulling
Yep, I'm referring that in the post (you probably missed it) "Now assuming that DerivedClass is instantiated and added to the QML context properly under the name of "DrvClass"" And yes, I'm using the setContextProperty() of the rootContext of the engine. - RuiDo
To fix undefined reference to 'vtable' int the DerivedClass -- Add Q_OBJECT macro and rerun qmake - nib

1 Answers

2
votes

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

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