QT QWebEnginePage::setWebChannel() 传输对象

QT QWebEnginePage::setWebChannel() transport object

我正在使用 QT WebEngine 框架来显示网页。我在页面加载时将 javascript 注入页面,并希望 javascript 能够访问 QT 对象。显然,要做到这一点,必须存在一个 QWebChannel,它在 Chromium(javascript)和我的 C++/QT 项目的其余部分之间建立一些 IPC。我遇到了 QWebEnginePage::setWebChannel (QWebChannel *channel) 函数,但是我找不到它的任何使用示例。文档 (http://doc.qt.io/qt-5/qwebenginepage.html#setWebChannel) mentions that qt.webChannelTransport should be available in the javascript context, but I don't see where that is established in qwebchannel.js (https://github.com/qtproject/qtwebchannel/blob/dev/src/webchannel/qwebchannel.js). I've seen the WebChannel examples (http://doc.qt.io/qt-5/qtwebchannel-examples.html) 并希望尽可能避免使用 WebSockets。

以下是我尝试实现网络频道的方式。

每当加载页面时,我都会建立一个通道并在 C++ 中注入 javascript:

QWebChannel *channel = new QWebChannel();
channel->registerObject(QStringLiteral("jshelper"), helper);

view->page()->runJavaScript(qwebjs); //this is qwebchannel.js
view->page()->setWebChannel(channel);
view->page()->runJavaScript(myfunction); //function that calls QT object (jshelper)

在Javascript中:

new QWebChannel(qt.webChannelTransport, function(channel) { ... });

这导致通道连接不正确(假设这是因为 qt.webChannelTransport,因为它在我使用 WebSockets 时工作正常)。任何以这种方式使用 QWebEnginePage 设置 QWebChannel 的示例的指针也很受欢迎。

简短回答:<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script> 添加到您的 html 页面(当然是在调用 new QWebChannel 之前),然后删除行 view->page()->runJavaScript(qwebjs); //this is qwebchannel.js 来自你的 C++ 代码。

长答案:

我在弄清楚如何在没有 WebSockets 的情况下正确使用 QWebChannel 时也遇到了很多麻烦——在深入研究 Qt 5.5 源代码和邮件列表(仍然缺乏文档)后设法让它工作。请注意,这仅适用于 the new Qt 5.5

QWebChannel 的使用方法如下:

// file: MyWebEngineView.cpp, MyWebEngineView extends QWebEngineView
QWebChannel *channel = new QWebChannel(page());

// set the web channel to be used by the page
// see http://doc.qt.io/qt-5/qwebenginepage.html#setWebChannel
page()->setWebChannel(channel);

// register QObjects to be exposed to JavaScript
channel->registerObject(QStringLiteral("jshelper"), helper);

// now you can call page()->runJavaScript(...) etc
// you DON'T need to call runJavaScript with qwebchannel.js, see the html file below

// load your page
load(url);

在 JS 方面:

<!-- NOTE: this is what you're missing -->
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>

<script type="text/javascript">
    <!-- it's a good idea to initialize webchannel after DOM ready, if your code is going to manipulate the DOM -->
    document.addEventListener("DOMContentLoaded", function () {
        new QWebChannel(qt.webChannelTransport, function (channel) {
            var jshelper = channel.objects.jshelper;
            // do what you gotta do
        });
    });
</script>

还要确保您已将 QT += webenginewidgets webchannel 添加到 .pro 文件中,否则无法构建!

奖励: 您现在可以从 Chrome 开发工具中舒适地调试您的 JavaScript!只需将其添加到您的 Qt 代码中的某处(最好是在您的应用程序启动时):

#ifdef QT_DEBUG
    qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "23654");
#endif

然后启动您的应用程序,导航至 Chrome 中的 http://localhost:23654,您将获得功能齐全的 JS 调试器、分析器、控制台等:)


跟进 (19/04/2016): 如果您的远程调试器不工作,请注意 qputenv 调用也必须发生 before 任何调用 QWebEngineSettings 或任何其他与 WebEngine 相关的 class,因为这些会立即触发 WebEngine "zygote" 进程(zygote 是父 QtWebEngineProcess,所有未来的 QtWebEngineProcesses 是分叉的)然后 qputenv 不能影响它。花了几个小时来追踪这个。