Wie bekomme ich Javascript in ein QWebView, um neue Instanzen von C++-basierten Klassen zu erstellen?
-
09-09-2019 - |
Frage
Ich habe erfolgreich ein C++-Objekt zu einem QWebFrame hinzugefügt mit addToJavaScriptWindowObjectund kann einen Slot dieses Objekts von JavaScript aufrufen.
Was ich aber wirklich möchte, ist, dass einer dieser Slots ein neues Objekt zurückgibt.Ich habe zum Beispiel einen Slot wie diesen, der eine von QObject abgeleitete Klasseninstanz zurückgibt:
MyObject* MyApp::helloWorld()
{
//MyObject is dervied from QObject
return new MyObject();
}
Ich kann diesen Slot so erfolgreich über Javascript aufrufen
var foo=myapp.helloWorld();
Aber Foo scheint leer zu sein, ich kann keine Slots aufrufen oder keine Eigenschaften davon von JavaScript aufnehmen.
Irgendwelche Ideen, wie ich das erreichen kann?
Lösung
Eine ziemlich hässliche Hack, den ich in Betracht gezogen habe, ist addToJavaScriptWindowObject zu verwenden, um das Objekt, das ich mit einem zufälligen Namen in das Fenster Objekt zurückkehren will fallen, haben dann meinen Schlitz den Namen des Objektinstanz zurückgeben statt:
QString MyApp::helloWorld()
{
//general a unique name for the js variable
QString name=getRandomVariableName();
//here's the object we want to expose to js
MyObject* pReturn=new MyObject();
//we make attach our object to the js window object
getWebFrame()->addToJavaScriptWindowObject(name, pReturn,
QScriptEngine::ScriptOwnership);
//tell js the name we used
return name;
}
Die JS geschrieben werden kann, zu überprüfen, ob der Rückgabewert ein String ist, und wenn ja, aus dem Fenster das Objekt greifen.
var foo=myapp.helloWorld();
if (typeof foo == "string")
{
foo=window[foo];
}
Ein wenig hässlich, aber erhalte ich durch, bis eine bessere Methode kommt. Zukunft Qt-Versionen werden die Skriptunterstützung vereinen, so dass sie alle auf der Javascript in WebKit basiert, so hoffentlich wird dies verbessern dann!
Andere Tipps
Sie können Ihr Objekt Zeiger auf einen QObject * und zurück, dass zuweisen.
QObject * obj = new MyObject();
return obj;
Das funktioniert für mich auf Qt Webkit-Port auf Linux.
QtScript hat die Vorstellung von Prototypen - die Sie einen C ++ Prototyp für einen Skript Wert erstellen kann. Wir untersuchen, ob wir QtScript mit Javascriptüberbrücken können - die sollte ergibt die Möglichkeit, auch Prototypen von WebKit JavaScript-Umgebung; http://doc.trolltech.com/ 4.5 / qtscript.html # Making-use-of-Prototyp-basierte Vererbung
Versuchen Sie, Ihr neues Objekt als QObject* und nicht als MyObject* zurückzugeben.Wenn Sie nur mit QtScript arbeiten, können Sie anrufen qScriptRegisterMetaType um etwas Code für die Konvertierung von MyObject*s in QScriptValues (oder QVariants) zu definieren, aber es scheint kein Äquivalent für die in QtWebKit verwendete JavaScript-Engine zu geben.
Ärgerlicherweise bedeutet dies, dass die Offenlegung Ihres internen Objektmodells für WebKit entweder einen separaten Satz von Proxy-Funktionen erfordert, die Ihre Objektzeiger in QObject*s konvertieren, oder die Verwendung von Adapterklassen, um dasselbe zu tun.
Diese Antwort beruht auf Paulus 'Antwort, aber ein bisschen vereinfacht. Getestet und funktioniert für Qt 5.3. Sie benötigen eine Fabrik, die ein Objekt instanziiert, und gibt dann einen QObject
Zeiger auf dieses Objekt. Die Objektklasse von QObject
erben, so dass es richtig in JavaScript funktioniert:
QObject * MyApp::createInstance(QString objname) {
MyClass * obj = new MyClass(this);
m_mainWindow->webView->page()->mainFrame()->addToJavaScriptWindowObject(objname, obj, QWebFrame::ScriptOwnership);
return obj;
}
Mit diesem können Sie die folgenden Aktionen von Javascript:
var myobject = MyApp.createInstance("obj1");
An diesem Punkt haben Sie sowie obj1
im globalen JavaScript-Namespace myobject
(sie nur Zeiger sind, so die beiden folgenden Werke zu tun:
myobject.testmethod();
obj1.testmethod();
An dieser Stelle können Sie connect
in JavaScript verwenden C ++ Signale zu JavaScript-Slots zu verbinden. Weitere Informationen zu dieser Technik hier: http://doc.qt.io/qt- 5 / QtWebKit-bridge.html