2015-11-14 39 views
7

基於QT QWebEnginePage::setWebChannel() transport objectQt: Cannot invoke shared object methods/properties from javascript我試圖做一個小演示來測試功能。請參閱下面的基本測試代碼。我的問題是:使用QWebChannel時未定義的屬性和返回類型

  • 在新的QWebChannel的JavaScript構建過程中,Qt控制檯中有很多打印對象的屬性?'''?''。沒有通知信號,並且不是常量,HTML中的值更新將被破壞!「。這是怎麼回事,我該如何解決?
  • 當試圖從javascript端檢索它們時,所有C++對象屬性都是未定義的。什麼是通過webchannel檢索屬性的正確方法?
  • 來自C++函數的所有返回值回到未定義...在javascript中接收C++返回值的正確方法是什麼?

.pro文件

QT  += core gui 
QT  += network webenginewidgets webchannel widgets 
TARGET = hfbTestWebChannel 
TEMPLATE = app 
SOURCES += hfbTestWebChannel.cpp 
RESOURCES += hfbTestWebChannel.qrc 

.html文件

<html> 
<body> 

<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script> 
<script type="text/javascript"> 

var theQtObj; 

function buttonA() 
{ 
     PrintLog("Button A:init") 
     if (typeof qt !== "undefined") 
     { 
      new QWebChannel(qt.webChannelTransport, function(channel) 
      { 
       theQtObj = channel.objects.theQtObj; 
       PrintLog(" done, now theQtObj=" + theQtObj.toString()); 
      }); 

     } 
     else 
      PrintLog("!!!qt undefined!!!"); 
} 

function buttonB() 
{ 
     PrintLog("Button B : call c++ and get some answers!") 
     if(typeof theQtObj !== "undefined") 
     { 
      var X = prompt("Enter a number", "5"); 
      PrintLog("theQtObj=" + theQtObj + " => X=" + X); 
      var n = theQtObj.getInt(X); 
      PrintLog(" back in js with n="+n); 
      var d = theQtObj.getDouble(n); 
      PrintLog(" back in js with d="+d); 
      var s = theQtObj.getString(d.toString()); 
      PrintLog("X:" + X + "->" + n + "->" + d + "->" + s); 
     } 
     else 
      PrintLog(" --> theQtObj not defined"); 
} 

function buttonC() 
{ 
     PrintLog("Button C:get c++ object member elements") 
     if(typeof theQtObj !== "undefined") 
     { 
      PrintLog("theQtObj._theString=" + theQtObj._theString); 
      PrintLog("theQtObj._theInt=" + theQtObj._theInt); 
     } 
     else 
      PrintLog(" --> theQtObj not defined"); 
} 


var x=0; 
function PrintLog(txt) 
{ 
    var myBox = document.getElementById("textBoxLog"); 
    myBox.value += ("\n" + x + ": " + txt); 
    myBox.scrollTop = myBox.scrollHeight; 
    return (x++); 
} 

</script> 

<p>Test Example to call Qt function from Javascript </p> 

<p> 
<input type="button" value=" A:init " onclick="buttonA()"> 
<input type="button" value=" B:get int " onclick="buttonB()"> 
<input type="button" value="C:get members" onclick="buttonC()"> 
</p> 

<p> 
<textarea id="textBoxLog" rows="31" cols="95"> 
textBoxLog 
</textarea> 
</p> 

</body> 
</html> 

.cpp文件

#include <QWebEngineView> 
#include <QApplication> 
#include <QtWebChannel/QtWebChannel> 

///////////////////////////////////////////////////////////////// 
class hfbDisplayWidget : public QWebEngineView 
{ 
    Q_OBJECT 

public: 
    hfbDisplayWidget(QWidget * parent) : QWebEngineView(parent) 
    { 
     page()->setWebChannel(&_webchannel); 
     _webchannel.registerObject(QString("theQtObj"), this); 

     _theString = "Hello World"; 
     _theInt = 777; 
    } 

    QWebChannel _webchannel; 

    Q_INVOKABLE QString _theString; 
    Q_INVOKABLE int _theInt; 

    Q_INVOKABLE int getInt(QVariant n) 
    { 
     int N = n.toInt(); 

     QString js = QString("PrintLog('c++ getInt(%1) fired!')").arg(N); 
     _theString = js; 
     _theInt = N; 

     page()->runJavaScript(js, [=](const QVariant &rslt){ 
      qDebug() << js << " -> " << rslt; 
     }); 
     return N*100; 
    } 

    Q_INVOKABLE double getDouble(QVariant d) 
    { 
     double D = d.toDouble(); 

     QString js = QString("PrintLog('c++ getDouble(%1) fired!')").arg(D); 
     page()->runJavaScript(js, [=](const QVariant &rslt){ 
      qDebug() << js << " -> " << rslt; 
     }); 

     return (D+0.12345); 
    } 

    Q_INVOKABLE QString getString(QVariant s) 
    { 
     QString S = s.toString(); 

     QString js = QString("PrintLog('c++ getString(%1) fired!')").arg(S); 
     page()->runJavaScript(js, [=](const QVariant &rslt){ 
      qDebug() << js << " -> " << rslt; 
     }); 

     return (QString("c++ called with:'") + S + QString("'")); 
    } 
}; 


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

    hfbDisplayWidget view(nullptr); 
    view.setUrl(QUrl("qrc:/hfbTestWebChannel.html")); 
    view.show(); 

    return a.exec(); 
} 
///////////////////////////////////////////////////////////////// 
///////////////////////////////////////////////////////////////// 

#include "hfbTestWebChannel.moc" 

*編輯添加的所有代碼的完整性

回答

1

我最近有同樣的問題。經過一番調查後,我想出瞭如何使其工作。非常感謝這個問題的答案:How to use Qt WebEngine and QWebChannel?

爲了獲得你的QObject的方法的返回值,你需要定義一個包裝你的QObject方法的Q_PROPERTY。例如:

class SharedObject : public QObject 
{ 
    Q_OBJECT 
public: 
    Q_INVOKABLE int getIntValue(); 
    Q_PROPERTY(int intValue READ getIntValue) 

    Q_INVOKABLE QString getStringValue(); 
    Q_PROPERTY(QString stringValue READ getStringValue) 
} 

然後在你的HTML,這樣做:

<script type="text/javascript"> 
    document.addEventListener("DOMContentLoaded", function() { 
     new QWebChannel(qt.webChannelTransport, function (channel) { 
     window.sharedObject = channel.objects.sharedObject; 
     alert("intValue: " + sharedObject.intValue); 
     alert("stringValue: " + sharedObject.stringValue); 
     }); 
    }); 
    </script> 

你應該能夠看到的intValue和stringValue的在你的JavaScript代碼。重要的是我想用Q_PROPERTY。

無論如何,這解決了我的問題,我希望它也可以幫助別人。

0

面臨同樣的問題......閱讀文檔仔細給了我答案。答案是在Qt5中Qt和JS之間的通信是異步的。您必須提供回調函數,該函數將在完成方法並收到結果值後調用。

與其說

var n = theQtObj.getInt(X); 
PrintLog(" back in js with n="+n); 

,你可以撥打作爲

theQtObj.getInt(X, function(n) { 
    PrintLog(" back in js with n="+n); 
});