使用QWebChannel时未定义的属性和返回类型

时间:2015-11-14 01:18:20

标签: javascript c++ qt

基于QT QWebEnginePage::setWebChannel() transport objectQt: Cannot invoke shared object methods/properties from javascript我尝试制作一个小型演示来测试功能。请参阅下面的基本测试代码。我的问题是:

  • 在新的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"

*编辑以添加完整性的所有代码

2 个答案:

答案 0 :(得分:2)

我最近遇到了同样的问题。经过一番调查,我想出了如何让它发挥作用。非常感谢这个问题的答案: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>

您应该能够在JavaScript代码中看到intValue和stringValue。重要的是我认为使用Q_PROPERTY。

无论如何,这解决了我的问题,我希望它对其他人也有帮助。

答案 1 :(得分:1)

面对同样的问题......阅读医生认真地给了我答案。答案是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);
});