javascript 如何使用 Qt WebEngine 和 QWebChannel?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28565254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 09:11:11  来源:igfitidea点击:

How to use Qt WebEngine and QWebChannel?

javascriptc++qtqtwebengineqtwebchannel

提问by user1185305

I'm using the new WebEngine to play around and learn. I've been trying to find some similar methods found using Qt WebKit: addToJavaScriptWindowObject()

我正在使用新的 WebEngine 来玩耍和学习。我一直试图找到一些使用 Qt WebKit 找到的类似方法:addToJavaScriptWindowObject()

I found that using Qt WebEngine, I have to use the QWebChannelto register functions to the JavaScript window object. If this is correct, it takes me to the following question.

我发现使用 Qt WebEngine 时,我必须使用 将QWebChannel函数注册到 JavaScript 窗口对象。如果这是正确的,那么我将回答以下问题。

I've installed Qt 5.4.0 on my computer. I noticed that qwebchannel.jsis not found in the SDK installed on my computer. I found it on the Git source.

我已经在我的电脑上安装了 Qt 5.4.0。我注意到qwebchannel.js在我的计算机上安装的 SDK 中没有找到。我在 Git 源上找到了它。

If I have a Qt native desktop application with a QWebEnginePageand QWebEngineView, what do I need to be able to register functions on the JavaScript window object?

如果我有一个带有QWebEnginePageand的 Qt 本机桌面应用程序,QWebEngineView我需要什么才能在 JavaScript 窗口对象上注册函数?

My desktop application navigates automatically to a http page that I have created. So I have access to the content connected to the QWebEngineView.

我的桌面应用程序会自动导航到我创建的 http 页面。所以我可以访问连接到QWebEngineView.

What are the steps to take so I can make this work?

需要采取哪些步骤才能完成这项工作?

回答by IAmInPLS

In Qt5.6, if you want to make C++ part and JavaScript to communicate, the only way to do it is using QWebChannelon a QWebEngineView, as you stated. You do it this way in the .cppfile:

在 Qt5.6 中,如果你想让 C++ 部分和 JavaScript 进行通信,唯一的方法就是在QWebEngineView上使用QWebChannel,正如你所说的。你在.cpp文件中这样做:

m_pView = new QWebEngineView(this);
QWebChannel * channel = new QWebChannel(page);
m_pView->page()->setWebChannel(channel);
channel->registerObject(QString("TheNameOfTheObjectUsed"), this);

Here, you just say that you register an object named TheNameOfTheObjectUsedthat will be available on the JS side. Now, this is the part of code to use in the JS side :

在这里,您只是说您注册了一个名为的对象TheNameOfTheObjectUsed,该对象将在 JS 端可用。现在,这是在 JS 端使用的代码部分:

new QWebChannel(qt.webChannelTransport, function (channel) {
            // now you retrieve your object
            var JSobject = channel.objects.TheNameOfTheObjectUsed;
        });

Now, if you want to retrieve some properties of the class in the JS side, you need to have a method on the C++ side which returns a string, an integer, a long... This is what it looks like on the C++ side, in your .h:

现在,如果你想在 JS 端检索类的一些属性,你需要在 C++ 端有一个方法,它返回一个字符串,一个整数,一个长......这是在 C++ 端的样子,在您的.h

Q_INVOKABLE int getInt();
Q_PROPERTY(int myIntInCppSide READ getInt);

And now, you get the int like this on the JS side :

现在,你在 JS 端得到这样的 int:

var myIntInJSside= JSobject.myIntInCppSide;

This is a very simple explanation, and I recommend you to watch this videowhich was very useful to me. Also, you might want to read more about the JavaScript APIprovided by QWebChannel, as well as the documentation about QWebChannel.

这是一个非常简单的解释,我建议您观看这个对我非常有用的视频。此外,您可能想阅读更多关于QWebChannel 提供的JavaScript API以及有关QWebChannel的文档。

Hope that helps!

希望有帮助!

回答by user

An alternative and much simpler way of communication with the page is to use runJavaScriptfunction:

与页面通信的另一种更简单的方法是使用runJavaScript函数:

view->page()->runJavaScript("alert('Hello from C++');");

It has its limitations: the call must be initiated from the C++ side and you can get only synchronous response from JS. But there is an upside too: no modification of the underlying webpage is necessary.

它有其局限性:调用必须从 C++ 端发起,您只能从 JS 获得同步响应。但也有一个好处:不需要修改底层网页。

Currently opened webpage can be accessed using QWebEngineView::page()function, as in the example above. During the navigation, the browser doesn't change the page until the next one is received from the network, so this function returns valid page object at any time. But your JS may still interrupt new page loading in a way that you'll appear in the document.readyState == 'loading'where the DOM tree is not yet constructed and some scripts on the page might not have been run yet. In this case you should wait for the DOMContentLoadedevent.

可以使用QWebEngineView::page()函数访问当前打开的网页,如上例所示。在导航过程中,浏览器在从网络接收到下一个页面之前不会更改页面,因此该函数随时返回有效的页面对象。但是您的 JS 可能仍然会以某种方式中断新页面的加载,您将出现在document.readyState == 'loading'尚未构建 DOM 树的位置,并且页面上的某些脚本可能尚未运行。在这种情况下,您应该等待DOMContentLoaded事件。

回答by bendiy

Qt has documentation on this now:

Qt 现在有这方面的文档:

Qt WebChannel Standalone Example

Qt WebChannel 独立示例

You have to add a QWebSocketServerto your cpp app that the QWebEngineView's HTML/Javascript will connect to using a WebSocket. Then use QWebChannelfor two way communication.

您必须向QWebSocketServercpp 应用程序添加,QWebEngineView的 HTML/Javascript 将使用 WebSocket 连接到该应用程序。然后QWebChannel用于双向通信。