Qml as script for C++ program, the Set function does not work.



  • I am trying to learn how to use a qml code as a script using QQmlEngine.
    I have a standard QMainWindow application with one push button on the main window.
    When i press the push button, it executes a QML file.
    Following is the sourcecode for the mainwindow and the qml file.

    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        qmlRegisterType<Testing>("com.script.Testing", 1, 0, "Testing");
    }
    void MainWindow::on_pushButton_clicked()
    {
        Testing *mytest = new Testing();
        QString filename = "E:/Mega Store File Backup/QtProjects/Scripting R&D/scripttest1/main.qml";
        QFile myqml(filename);
        if(!myqml.exists())
        {
            qDebug()<<"File does not exist";
            return;
        }
           QQmlEngine engine;
    //       QQmlContext *objectContext = new QQmlContext(engine.rootContext());
           QQmlComponent component(&engine, QUrl::fromLocalFile(filename));
           QObject *object = component.create();//(objectContext);
    }
    // The testing class .h and cpp files are as given here.
    class Testing : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged)
    
    public:
        explicit Testing(QObject *parent = nullptr);
    
    
        QString userName();
        void setUserName(const QString &userName);
    
    public slots:
        void setMyUserName(QString value);
    
    signals:
        void userNameChanged();
    
    private:
        QString m_userName;
    };
    
    Testing::Testing(QObject *parent) :
        QObject(parent)
    {
        m_userName="Hello Testing";
    }
    
    QString Testing::userName()
    {
        return m_userName;
    }
    
    void Testing::setUserName(const QString &userName)
    {
        qDebug()<<m_userName;
        if (userName == m_userName)
            return;
    
        m_userName = userName;
        emit userNameChanged();
    }
    
    void Testing::setMyUserName(QString value)
    {
        qDebug()<<value;
    }
    
    // The QML file is as follows.
    import QtQuick 2.6
    import QtQuick.Controls 2.0
    import com.script.Testing 1.0
    
    ApplicationWindow {
        id: root
        width: 300
        height: 480
        visible: true
    
        Testing {
            id: best
        }
    
        TextField {
            text: best.userName
            placeholderText: qsTr("User name")
            anchors.centerIn: parent
            onTextChanged: best.userName = text
            Component.onCompleted: {
                best.userName = text
            }
        }
        Label {
            id:status
            text: "Waiting for the event."
        }
    }
    

    Here when i run this, it executes. I see the window with the textfield with the default value assigned. However, when i change the value in text field, the qdebug does not print anything.
    I am unable to find the reason. Tried many things but did not succeed.


  • Moderators

    It looked weird that your code didn't work. Everything looks correct. So I decided to type up an example using similar code to yours. I did not cut and paste, but mine worked fine.

    Here is a zip of the project so you can build and test on your system. It works properly on mine. Maybe it will help you find the problem, I don't see it just by reading the code though, everything you have looks correct.

    example project

    Edit: in my example I forgot to emit the change signal on setUserName, just in case you use that code for something don't forget to add that, lol.



  • I'm guessing that is because you are creating your engine and component on the stack and they are going out of scope. Try allocating them on the heap.


  • Moderators

    @mranger90 Good call, in my example mine don't go out of scope. I didn't catch that when I looked over his code. :) Sounds like you're on to something there.



  • @ambershark @mranger90
    I saw your code, There is a major difference between the way you are running the application and I am running the application.
    If I run the application as a qml application, the application runs well. No problem at all.

    However, I am trying to run it the way a scripting language should work or what I expect it to work.
    I am running the main.qml without including in the Resources. I want to be able to do that at run time. Including it in Resources defeats the purpose.

    Secondly, I am running the qml through the mainform.cpp at runtime. So Ideally i want to select the qml file to run and then run it.
    Which works as far as running the qml is concerned. However, when it comes to interaction of the testing.cpp and the qml, that does not work.

    I have attached the zip of the complete project in qtcreator FYI.

    [0_1536639580948_scripttest1.zip](Uploading 100%)