2015-11-14 12 views
7

Basato su QT QWebEnginePage::setWebChannel() transport object e Qt: Cannot invoke shared object methods/properties from javascript Ho provato a creare una piccola demo per testare la funzionalità. Vedi il codice di test di base qui sotto. Le mie domande sono:Proprietà non definite e tipi di ritorno quando si utilizza QWebChannel

  • Durante la costruzione javascript del nuovo QWebChannel, ci sono molte stampe nella console Qt per "Proprietà"? "Dell'oggetto"? " non ha un segnale di notifica e non è costante, gli aggiornamenti di valore in HTML saranno interrotti! ". Di cosa si tratta, come lo risolvo?
  • Tutte le proprietà dell'oggetto C++ non sono definite quando si tenta di recuperarle dal lato JavaScript .. qual è il modo corretto per recuperare le proprietà sul webchannel?
  • Tutti i valori restituiti dalle funzioni C++ vengono restituiti come non definiti ... qual è il modo corretto per ricevere il valore restituito da C++ in javascript?

di file .pro

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

.html il file

<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> 

file 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" 

* Modifica per aggiungere tutto il codice per completezza

risposta

1

Ho avuto lo stesso problema di recente. Dopo alcune indagini, ho capito come farlo funzionare. Grande grazie alla risposta di questa domanda: How to use Qt WebEngine and QWebChannel?

Per ottenere il valore di ritorno di un metodo del QObject, è necessario definire un Q_PROPERTY che avvolge il metodo QObject. Per esempio:

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) 
} 

E poi nel codice HTML, fare questo:

<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> 

si dovrebbe essere in grado di vedere e intValue stringValue nel codice JavaScript. L'importante è usare Q_PROPERTY, penso.

In ogni caso, questo risolve il mio problema, e spero che aiuti anche qualcun altro.

0

Di fronte allo stesso numero ... Leggendo attentamente il documento mi ha dato la risposta. La risposta è che la comunicazione tra Qt e JS in Qt5 è asincrona. È necessario fornire la funzione di richiamata che verrà chiamata dopo il completamento del metodo e il valore del risultato ricevuto.

Invece di chiamare

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

è possibile chiamare a come

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