11

How to pass a function "pointer" from JavaScript to a slot?

in JavaScript:

function f1()
{
    alert("f1");
}
qtclass.submit(f1);

and in Qt:

public slots:
    void submit(void * ptr) 
    {
        (void)ptr;
    }

I need the "f1", function to get fired in the JavaScript from the c++, once some processing is done. Also I do not know in advance the name of the function pointer.

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
user457015
  • 960
  • 4
  • 14
  • 33

4 Answers4

9

you should be able to execute your script using QWebFrame::evaluateJavaScript method. See if an example below would work for you:

initializing webview:

QWebView *view = new QWebView(this->centralWidget());
view->load(QUrl("file:///home//test.html"));
connect(view, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));

loadFinished signal handler:

void MyTestWindow::loadFinished(bool)
{
    QVariant f1result = ((QWebView*)sender())->page()->mainFrame()->evaluateJavaScript("f1('test param')");
    qDebug() << f1result.toString();
}

test.html:

<head>
    <script LANGUAGE="JavaScript">
        function f1 (s) 
        {
            alert (s) 
            return "f1 result"
        }
    </script>
</head>
<body>
    test html
</body>

evaluateJavaScript should trigger an alert message box and return QVariant with f1 function result.

hope this helps, regards

serge_gubenko
  • 20,186
  • 2
  • 61
  • 64
6

You could solve this in another way, by using Qt signals, as follows:

class qtclass
{
   signals:
      void done(QString message);
};

In your HTML file you can connect to this signal, like this:

qtclass.done.connect(f1);

function f1(message)
{
   alert('f1 called from qtclass with message' + message);
}

Then you C++ class does not need to know about the javascript function.

Kurt Pattyn
  • 2,758
  • 2
  • 30
  • 42
  • I am trying to follow your answer, and doing the same thing. However, it is not working for me. Here is my question - http://stackoverflow.com/questions/22037838/qt-qweb-callback-not-working-in-the-example-here . Can you please spare some time to answer on it? – dexterous Feb 26 '14 at 12:33
  • Would you mind answering this question, http://stackoverflow.com/questions/22060192/why-callback-to-js-is-not-working-in-the-qtweb-using-signals-in-the-following-co – dexterous Feb 27 '14 at 09:28
  • What is qtclass in your JS code? How do u linked it? – borune Feb 26 '18 at 07:35
3

While it wouldn't work in all cases, you could simply pass a string to your slot. Your slot could then use evaluateJavaScript (as serge has suggested) to call the function.

function f1()
{
    alert("f1");
}
qtclass.submit("f1");

and in Qt:

public slots:
    void submit(QString functionName) 
    {
        m_pWebView->page()->mainFrame()->evaluateJavaScript(functionName + "()");
    }
Noah Callaway
  • 617
  • 5
  • 16
1

I have one entire working solution here - using slots. However, I couldn't get the signals working as suggested by Kurt.

#include <QtGui/QApplication>
#include <QApplication>
#include <QDebug>
#include <QWebFrame>
#include <QWebPage>
#include <QWebView>

class MyJavaScriptOperations : public QObject {
    Q_OBJECT
public:
     QWebView *view;
     MyJavaScriptOperations();

    Q_INVOKABLE qint32 MultOfNumbers(int a, int b) {
        qDebug() << a * b;
        return (a*b);
    }
public slots:
     void callback();
public:

void  firecb();

 signals:
      void done();
};


MyJavaScriptOperations::MyJavaScriptOperations()
{
    view = new QWebView();
    view->resize(400, 500);

    connect(view->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(callback()));

    view->load(QUrl("./shreyas.html"));

    view->show();


    qDebug()<<view;


}

void MyJavaScriptOperations::callback()
{
    qDebug()<<"Sending hello text";
    QString function = "f1()";
    view->page()->mainFrame()->addToJavaScriptWindowObject("myoperations", this);
    view->page()->mainFrame()->evaluateJavaScript("f1()");
    done();
}

void  MyJavaScriptOperations::firecb()
{
     qDebug()<<"Emitting Signal";
     done();
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);


    MyJavaScriptOperations *jvs = new MyJavaScriptOperations;
    jvs->firecb();

    return a.exec();
}
#include "main.moc"

The html file changes are -

<head>
    <script LANGUAGE="JavaScript">


function f1()
{
   alert('f1 called from qtclass with message');
   document.write("HELLLLLLLLL");
}
myoperations.callback(f1);


function f2()
{
   var result = myoperations.MultOfNumbers(3,7);
   document.write(result);
    alert('f1 called from qtclass with message');
}


function f3()
{

    alert('f3');
}

myoperations.done.connect(f3);


    </script>
</head>
<body>
    test html
<input type="button" value="click" onclick="f2()">
</body>
dexterous
  • 6,422
  • 12
  • 51
  • 99