Need working example code to expose C++ class to QJSEngine



  • I've studied the documentation and also researched online for help, but it seems like things are not crystal clear.
    I don't understand how a class should be built such that it can be exposed to the javascript environment in QJSEngine.
    So, suppose I have the next class:
    -- testclass.h

    #include <QObject>
    class QString;
    
    class testclass : public QObject{
    	Q_OBJECT
    public:
    	testclass();
    
    	int getPropOne() const;
    	void setPropOne(const int);
    
    	QString getPropTwo() const;
    	void setPropTwo(const QString &);
    
    private:
    	int one;
    	QString two;
    };
    

    -- testclass.cpp

    #include "testclass.h"
    #include <QString>
    
    testclass::testclass(){
    	one = 1;
    	two = "two";
    }
    
    int testclass::getPropOne() const {
    	return one;
    }
    
    void testclass::setPropOne(const int newvalue){
    	one = newvalue;
    }
    
    QString testclass::getPropTwo() const {
    	return two;
    }
    
    void testclass::setPropTwo(const QString &val){
    	two = val;
    }
    

    Can you please show me some working code that would:

    • expose an object of class "testclass" from C++ to the QJSEngine environment;
    • make it possible to instantiate new objects of type "testclass" directly from the QJSEngine environment

    Also, I'm sure I've read it somewhere but can't find it anymore... I remember the only objects I can expose from C++ to the QJSEngine environment are those derived from QObject, and must contain the Q_OBJECT macro. Can you confirm that? The documentation is very poor on QJSEngine and I'm sorry to ask you such basic questions. Thank you in advance to those willing to help me.



  • On this page (http://doc.qt.io/qt-5/qtjavascript.html), the section 'Making a QObject Available to the Script Engine' has some info but I know it's not much. It mentions, in not so many words, that an instance of QObject-based class is needed if you want it accessible in JavaScript.

    In general, here's what I've needed to do before:

    1. Create a class that is derived from QObject and add the Q_OBJECT macro.
    2. The function-to-be-called must be under a section with 'slots'. For example, 'public slots' or 'protected slots'.
    3. With an instance of that QObject-derived class, create a JavaScript object (using QJSEngine::newQObject) and assign it to a property on the Global Object associated with the script engine (using QJSValue::setProperty).

    You've done #1. To do #2, in testclass.h, add

    public slots:
    

    on a line before

    int getPropOne() const;
    

    Here's an example on how to do #3:

    testclass* myTestClass = new testclass();
    QJSEngine jsEngine;
    QJSValue myTestClassObject = jsEngine.newQObject( myTestClass );
    QJSEngine jsEngine.globalObject().setProperty( "myTestClass", myTestClassObject );
    

    Within your JavaScript code, you should now be able to make calls like myTestClass.getPropOne().

    About your second question, I don't know if it's possible to instantiate new 'testclass' objects directly in JavaScript. I think not but I have nothing to back that up.



  • Thank you very much, your answer is really helpful!

    I will investigate more about instantiating new objects but for now I could only find how to do that from QML. I remember though that it needed some createNew() method in the class that would return the new object... I don't really know how this works but If someone has any idea let me know.



  • Have you tried what the person in this post did: https://forum.qt.io/topic/57809/qjsengine-q_invokable-method-that-returns-pointer-to-subclass-of-qobject

    I've not tried it out myself but it looks like you'll need to register testclass using qmlRegisterType and prepend Q_INVOKABLE to the 'createNew' function that returns the new object.



  • Right now I am confused about the correlation between QML and QJSEngine. I mean, the QJSE is supposed to provide a JS interpreter and (possibly) all the functionality to interact between JS and C++. So, to some extent, QJSEngine is supposed to be complete on its own, without needing QML. I think, the poor documentation on this part lacks to mention the proper interaction between the two which consequently confuses people on what they actually need for the task.

    I will try looking through all the documentation about QML and QJSEngine, hopefully I'll understand more about them. And I'll try to use the Q_INVOKABLE way. I'll be back with news as soon as I get something to work.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.