Search code examples
c++qtqt5qtscript

QT qScriptConnect is not working


QScriptEngine eng;
QScriptEngineDebugger debugger;
debugger.attachTo(&eng);
QScriptValue consoleObj =  eng.newQObject(this);
eng.globalObject().setProperty("asd", consoleObj);
QScriptValue handler= eng.evaluate("(function(text) { asd.log('text was changed to '+text); })");
QLineEdit *edit = new QLineEdit(this);
qScriptConnect(edit, SIGNAL(textChanged(QString)), QScriptValue(), handler);
edit->show();

qScriptConnect(edit, SIGNAL(textChanged(QString)), QScriptValue(), handler) is not working, but when i am using handler.call(QScriptValue(),args) it works well;

QScriptValueList args;
args << 3;
handler.call(QScriptValue(),args);

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
      Q_INVOKABLE void log(QString msg);
    ~MainWindow();

private slots:

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<qscriptengine.h>
#include<qscriptenginedebugger.h>
#include<qlineedit.h>
#include<qdebug.h>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QScriptEngine eng;
    QScriptEngineDebugger debugger;
    debugger.attachTo(&eng);
    QScriptValue consoleObj =  eng.newQObject(this);
    eng.globalObject().setProperty("asd", consoleObj);
    QScriptValue handler= eng.evaluate("(function(text) { asd.log('text was changed to '+text); })");
    QLineEdit *edit = new QLineEdit(this);
    qDebug()<<qScriptConnect(edit, SIGNAL(textChanged(QString)), QScriptValue(), handler);
    edit->show();
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::log(QString msg)
{
    qDebug() << "jsConsole: "<< msg;
}

Solution

  • A variable created in a method that is not created in the heap is deleted when it finishes executing the method, in your case the QScriptEngine is created in the constructor reason why it is eliminated, and all the script depends on it. The solution is simple, make the QScriptEngine member of the class:

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QScriptEngine>
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
        Q_INVOKABLE void log(const QString & text);
    
    private:
        Ui::MainWindow *ui;
        QScriptEngine eng; // member
    };
    
    #endif // MAINWINDOW_H
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include <QLineEdit>
    #include <QScriptEngine>
    #include <QScriptEngineDebugger>
    
    #include <QDebug>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        QScriptEngineDebugger debugger;
        debugger.attachTo(&eng);
        QScriptValue consoleObj =  eng.newQObject(this);
        eng.globalObject().setProperty("asd", consoleObj);
        QScriptValue handler= eng.evaluate("(function(text) { asd.log('text was changed to '+text); })");
        QLineEdit *edit = new QLineEdit(this);
        qScriptConnect(edit, SIGNAL(textChanged(QString)), QScriptValue(), handler);
        edit->show();
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::log(const QString &text)
    {
        qDebug()<< text;
    }