2015-08-10 15 views
8

Ich verwende das QT WebEngine-Framework, um Webseiten anzuzeigen. Ich injiziere Javascript in eine Seite, wenn es geladen wird, und möchte dem Javascript erlauben, auf ein QT-Objekt zugreifen zu können. Anscheinend muss dazu ein QWebChannel vorhanden sein, der eine IPC zwischen Chrom (dem Javascript) und dem Rest meines C++/QT-Projekts herstellt. Ich bin auf die Funktion QWebEnginePage :: setWebChannel (QWebChannel * channel) gestoßen, kann jedoch keine Beispiele für ihre Verwendung finden. Die Dokumentation (http://doc.qt.io/qt-5/qwebenginepage.html#setWebChannel) erwähnt, dass qt.webChannelTransport im JavaScript-Kontext verfügbar sein sollte, aber ich sehe nicht, wo das in qwebchannel.js (https://github.com/qtproject/qtwebchannel/blob/dev/src/webchannel/qwebchannel.js) festgelegt ist. Ich habe die WebChannel-Beispiele (http://doc.qt.io/qt-5/qtwebchannel-examples.html) gesehen und möchte WebSockets möglichst vermeiden.QT QWebEnginePage :: setWebChannel() Transportobjekt

Unten ist, wie ich versucht habe, den Web-Kanal zu implementieren.

Jedes Mal, wenn eine Seite geladen ich einen Kanal aufzubauen und das Javascript in C injizieren ++:

QWebChannel *channel = new QWebChannel(); 
channel->registerObject(QStringLiteral("jshelper"), helper); 

view->page()->runJavaScript(qwebjs); //this is qwebchannel.js 
view->page()->setWebChannel(channel); 
view->page()->runJavaScript(myfunction); //function that calls QT object (jshelper) 

In Javascript:

new QWebChannel(qt.webChannelTransport, function(channel) { ... }); 

, die in den Kanal führt nicht richtig angeschlossen ist (Angenommen, dies ist wegen qt.webChannelTransport, wie es funktionierte, als ich WebSockets verwendete). Alle Verweise auf Beispiele von QWebChannel, die auf diese Weise mit QWebEnginePage eingerichtet werden, werden ebenfalls geschätzt.

Antwort

20

Kurze Antwort: hinzufügen <script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script> auf Ihre HTML-Seite (bevor Sie new QWebChannel natürlich nennen), und entfernen Sie die Zeile view->page()->runJavaScript(qwebjs); //this is qwebchannel.js von Ihrem C++ Code.

Lange Antwort:

Auch ich hatte eine Menge Mühe, herauszufinden, wie QWebChannel richtig ohne WebSockets verwenden - geschaffen, um es nach Graben um in Qt 5.5-Quellcode und Mailinglisten erhalten arbeitet (Dokumentation fehlt noch). Beachten Sie, dass dies nur mit the new Qt 5.5 funktioniert.

Hier ist, wie QWebChannel verwenden:

// file: MyWebEngineView.cpp, MyWebEngineView extends QWebEngineView 
QWebChannel *channel = new QWebChannel(page()); 

// set the web channel to be used by the page 
// see http://doc.qt.io/qt-5/qwebenginepage.html#setWebChannel 
page()->setWebChannel(channel); 

// register QObjects to be exposed to JavaScript 
channel->registerObject(QStringLiteral("jshelper"), helper); 

// now you can call page()->runJavaScript(...) etc 
// you DON'T need to call runJavaScript with qwebchannel.js, see the html file below 

// load your page 
load(url); 

Und auf der Seite JS:

<!-- NOTE: this is what you're missing --> 
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script> 

<script type="text/javascript"> 
    <!-- it's a good idea to initialize webchannel after DOM ready, if your code is going to manipulate the DOM --> 
    document.addEventListener("DOMContentLoaded", function() { 
     new QWebChannel(qt.webChannelTransport, function (channel) { 
      var jshelper = channel.objects.jshelper; 
      // do what you gotta do 
     }); 
    }); 
</script> 

Auch stellen Sie sicher, QT += webenginewidgets webchannel auf Ihre .pro Datei sonst diese bauen nicht hinzugefügt haben!

Bonus: Sie können Ihre JavaScript jetzt bequem von Chrome Dev Tools debuggen!Fügen Sie einfach diesen irgendwo in Ihrem Qt-Code (im Idealfall in der Anwendung Start):

#ifdef QT_DEBUG 
    qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "23654"); 
#endif 

dann Ihre Anwendung starten, navigieren Sie zu http://localhost:23654 in Chrome, und Sie erhalten eine voll funktionsfähige JS Debugger, Profiler, Konsole zu erhalten, etc :)


Follow-up (19/04/2016): wenn Ihr Remote-Debugger nicht funktioniert, beachten Sie, dass die qputenv Anruf auch vor Anrufe zu QWebEngineSettings oder anderen auftreten müssen WebEngine-bezogene Klasse, weil thes e löst den WebEngine "zygote" -Prozess sofort aus (die Zygote ist der übergeordnete QtWebEngineProcess, von dem alle zukünftigen QtWebEngineProcesses gegabelt werden) und kann dann qputenv nicht beeinflussen. Hab ein paar Stunden damit verbracht, das aufzuspüren.

+0

Das ist großartig-- mein einziges Problem ist, dass ich die Skripte injizieren muss, da ich keine Kontrolle über die Seiten habe, die geladen werden. Auch wenn du "das neue QT 5.5" sagst, meinst du das vom Dev-Zweig? Ich verwende QT Creator 5.5.0 und bin mir nicht sicher, wie der QT-Quellcode, von dem ich arbeite, aktualisiert wurde. Ich habe versucht, die Umgebungsvariable Einstellung zu JS in einer Konsole zu debuggen, aber es funktioniert nicht (ich denke, weil diese Debug-Option von einem letzten Commit ist). – mathieujofis

+0

Ich sehe. Navigieren Sie in Qt Creator zu Extras> Optionen> Erstellen und Ausführen> Qt-Versionen und prüfen Sie, welche Version Sie haben. Wenn ich Qt 5.5 sage, meine ich [die stabile Version, die am 1. Juli dieses Jahres veröffentlicht wurde] (http://blog.qt.io/blog/2015/07/01/qt-5-5-released/) . Qt 5.5 hat integrierte Unterstützung für Chromium IPC über QWebChannel hinzugefügt (d. H. "QWebEnginePage :: setWebChannel()" und "qt.webChannelTransport" in JS). Außerdem kann Ihr Qt Creator nicht unter Version 5.5 sein, [die neueste Version ist v3.4.2] (http://blog.qt.io/blog/2015/07/01/qt-creator-3-4-2- freigegeben /) :) –

+0

Auch die 'QTWEBENGINE_REMOTE_DEBUGGING' ist in der Qt 5.5-Version vorhanden: http://Stackoverflow.com/a/29721197/504611 –