Reputation: 1054
I have started to dig in to C++ and Qt again, and have been mucking around with the WebKit Javascript/Qt bindings. I've got all the moving parts working, with the exception of my QObject subclass being "undefined" on the Javascript side. Here's the simple test app I'm having trouble with:
My main window implementation:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// instantiate a webview
QWebView *webview = new QWebView(this);
webview->setGeometry(0, 0, 400, 300);
webview->setUrl(QUrl("file://localhost/Users/kyle/Sites/tests/qt/index.html"));
// instantiate and attach our QObject
hello *h = new hello();
QWebFrame *frame = webview->page()->mainFrame();
frame->addToJavaScriptWindowObject("Hello", h);
// show the window
webview->show();
}
Hello.cpp
...snip...
QString hello::say()
{
return QString("Kyle");
}
Hello.h
...snip includes...
class hello : public QObject
{
Q_OBJECT
public:
hello();
Q_INVOKABLE QString say();
};
The above-mentioned index.html file does a simple alert(Hello.say())
call, but doing typeof Hello
, I get undefined.
I'm a bit rusty with C++, and pretty new to Qt, so I'm sure this is a noob mistake, but I'm stumped.
Upvotes: 2
Views: 7417
Reputation: 29896
Objects can't be inserted in the page at any time. You should put that line:
frame->addToJavaScriptWindowObject("Hello", h);
in a slot connected to the javaScriptWindowObjectCleared()
signal of the QWebFrame
and move some code around, so you can access the frame from that slot.
See also the Form Extractor example included with Qt.
Upvotes: 6
Reputation: 2858
The core of this is really implemented in two methods, which are shown below:
void MyApi::setWebView( QWebView *view )
{
QWebPage *page = view->page();
frame = page->mainFrame();
attachObject();
connect(frame, &QWebFrame::javaScriptWindowObjectCleared, this, &MyApi::attachObject);
// old approach
//connect( frame, SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(attachObject()) );
}
void MyApi::attachObject()
{
frame->addToJavaScriptWindowObject( QString("MyApi"), this );
}
This code is all that you need in order to make all of the public slots of the MyApi object visible to javascript. The MyApi class provides two public slots:
public slots:
void doSomething( const QString ¶m );
int doSums( int a, int b );
The first slot simply logs a message to the debug output, the second returns the sum of its two arguments (yes, slots can return things!). They're called from javascript like this:
MyApi.doSomething( 'Hello from JS page 2!!!!' );
sum = MyApi.doSums( 2, 3 );
alert( 'C++ says the sum is ' + sum );
The code above was tested in QT5.5, and please note all methods should be put in "public slots" section.
Upvotes: 0