使用 QWebChannel 时未定义的属性和返回类型
Posted
技术标签:
【中文标题】使用 QWebChannel 时未定义的属性和返回类型【英文标题】:Undefined properties and return types when using QWebChannel 【发布时间】:2015-11-14 01:18:20 【问题描述】:基于QT QWebEnginePage::setWebChannel() transport object和Qt: Cannot invoke shared object methods/properties from javascript我尝试做一个小demo来测试功能。请参阅下面的基本测试代码。我的问题是:
在新 QWebChannel 的 javascript 构建过程中,Qt 控制台中有大量打印为“对象 '?' 的属性 '?''没有通知信号并且不是恒定的,html 中的值更新将被破坏!”。这是怎么回事,我该如何解决? 在尝试从 javascript 端检索它们时,所有 C++ 对象属性都未定义。通过网络通道检索属性的正确方法是什么? 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】:面临同样的问题...仔细阅读文档给了我答案。答案是 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);
);
【讨论】:
这是!!应该被接受为正确答案。也感谢得到解释,谢谢。【参考方案2】:我最近遇到了同样的问题。经过一番调查,我想出了如何让它工作。非常感谢这个问题的答案:How to use Qt WebEngine and QWebChannel?
为了获得你的 QObject 方法的返回值,你需要定义一个 Q_PROPERTY 包装你的 QObject 方法。例如:
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。
无论如何,这解决了我的问题,我希望它对其他人也有帮助。
【讨论】:
以上是关于使用 QWebChannel 时未定义的属性和返回类型的主要内容,如果未能解决你的问题,请参考以下文章
未捕获的 ReferenceError:未定义 QWebChannel
CoreData:第一次加载 NSManagedObject 时未访问自定义属性访问器