3

In qt4 qml the qtwebkit 1.0 the component webview has a property javaScriptWindowObjects. I used it to add javaScriptWindowObjects to the context of my webpages javascript to call c++ functions. like so

WebView{
    url: "http://test.com"
    anchors.fill: parent
    scale: 1.0

    javaScriptWindowObjects: QtObject {
        WebView.windowObjectName: "native"

        function foo(x, y) {
             console.log("This is a call from javascript");
             myCppHandler.fooNative(b,c);
         }
    }
}

so i can call it from the webpages javascript like so

<script type="text/javascript">
    native.foo(1,2)
</script>

but in qt5 qml qtwebkit 3.0 there is no such thing like javaScriptWindowObjects

how can i achieve that in qt5 qml?

dustin.b
  • 1,275
  • 14
  • 33

2 Answers2

6

Just for the record to get this done:

import QtQuick 2.0
import QtWebKit 3.0
import QtWebKit.experimental 1.0

Rectangle {

   width: 1024
   height: 768

   WebView{
       url: "http://localhost"
       anchors.fill: parent

       experimental.preferences.navigatorQtObjectEnabled: true
       experimental.onMessageReceived: {

           console.debug("get msg from javascript")
           experimental.postMessage("HELLO")
       }
   } // webview
} // rectanlge


<html>
<body>
<h1>It just works!</h1>

<p>Play with me...</p>

<button onclick="nativecall();">test</button>
<div id="out"></div>

<script type="text/javascript">
    function nativecall(){
        console.log("will try native call");
        var elem = document.getElementById("out").innerHTML="clicked";
        navigator.qt.postMessage('this is a js call');
    }

    function jsCall(message){
        var elem = document.getElementById("out").innerHTML="and the other way around " + message;
    }

    navigator.qt.onmessage = function(ev) {
        jsCall(ev.data);
    }
</script>

</body>
</html>
dustin.b
  • 1,275
  • 14
  • 33
  • This is fascinating, but I found that when turning on Experimental mode, even though I got the extra functionality, some odd things happened to the page controls. The checkboxes and radio buttons got wonky, the scrollbars disappeared (if I turned them on with DIVs), and the SELECT element stopped working. It's definitely a tech preview only in Qt 5.5 -- not ready for primetime. – Volomike Nov 20 '15 at 05:37
  • @Volomike i didn't invest much time for qml recently and especially in this topic since the release of this application was back in march 2013. I am wondering you consider this a preview. at the time of writing it was. Today i would guess there is a stronger Implementation out there not prefixed "experimental". Unfortunately i've no time as of right now to investigate this further, but this answer seems to be outdated and needs "refactoring" anyway. – dustin.b Nov 20 '15 at 08:17
  • Qt 5.6 is beta as of 2015 Nov 20, but they do include QtWebView (not to be confused with QWebView) in it with the tech preview of Minibrowser as well. I haven't tried Qt 5.6 beta yet. Meanwhile, there's a lively discussion going on with developers upset about the web component direction in Qt after 5.5 here: http://forum.qt.io/topic/55504/anyone-knows-the-future-of-qt-webkit – Volomike Nov 20 '15 at 08:31
  • 1
    @Volomike Thx i'll probably read it in its entirety when i got home from work ... the first few post are not that encouraging :/ i thought after nearly 3 years webkit was fully replaced by webengine that sounds awfully sad :( – dustin.b Nov 20 '15 at 08:45
  • There are other options, perhaps, if needing this for OSX or iOS. For instance, MacGap1 (available on Github), and perhaps a way to glue that to Qt/C++ (or Qt/whatever language). Or, do the work in native XCode against the webkit library there, and then have it call your Qt dynlibs. – Volomike Nov 20 '15 at 09:09
  • Can this be done with new `WebEngineView`? I tried but failed with `Cannot assign to non-existent property "preferences"`. I'm using Qt 5.7.0 on Windows. – zhm Nov 17 '16 at 13:51
0

Qt 5.8.0 QML & JavaScript binding

QML code

import QtQuick 2.0
import QtWebEngine 1.4
import QtWebChannel  1.0

Item{
    id:root
    height: 500
    width:  500

// Create WebChannel
WebChannel{
    id:webChannel
}

//Now, let’s create an object that we want to publish to the HTML/JavaScript clients:
QtObject {
    id: myObject
    objectName: "myObject"

    // the identifier under which this object
    // will be known on the JavaScript side
    //WebChannel.id: "webChannel"

    property var send: function (arg) {
                sendTextMessage(arg);
            }

    // signals, methods and properties are
    // accessible to JavaScript code
    signal someSignal(string message);


    function someMethod(message) {
        console.log(message);
        someSignal(message);
        return dataManager.getGeoLat();
    }

    property string hello: "world";
}

Rectangle{
    anchors.fill: parent
    color: "black"

WebEngineView{
    id : webEnginView
    anchors.fill: parent
    url : dataManager.htmlURL();
    webChannel: webChannel
}
}

Component.onCompleted: {
    webChannel.registerObject("foo", myObject);
}
}

HTML Code

<script type="text/javascript" src="qrc:/Map/qwebchannel.js"></script>
<script type="text/javascript">
new QWebChannel(qt.webChannelTransport, function(channel) {
    // all published objects are available in channel.objects under
    // the identifier set in their attached WebChannel.id property
    var foo = channel.objects.foo;

    // access a property
    alert(foo.hello);

    // connect to a signal
    foo.someSignal.connect(function(message) {
        alert("Got signal: " + message);
    });

    // invoke a method, and receive the return value asynchronously
       foo.someMethod("bar", function(ret) {
       alert("Got return value: " + ret);
    });
});
</script>
SourabhKus
  • 818
  • 8
  • 23