最清晰Qt与JS通过qwebchannel交互例子

tags: Qt javascript qwebchannel QWebEngineView


由来

在Qt平台上有很多很棒的图表控件,比如QWT,QCustomPlot,以及Qt5.5以后自带的QChart,但与JS网页端的各种绚丽效果控件比,还是差了不少。这次就是打算把百度出品的EChart控件应用在Qt端。
而在这样的跨平台调用中,很多文章都写的含糊其词,让人晕头转向,于是写一篇记录下最清晰最简单的调用过程。

工具

Qt5.5以上,在安装时选择上QWebEngine
同时必须选择基于VS编译器的Qt版本,基于MinGW的编译不能通过,原因可能是GCC不支持QWebEngine。
在这里插入图片描述

工程配置

1.新建基于Widget的工程
2..pro里加入

QT       += core gui webenginewidgets webchannel

.h里引用头文件

#include <QWebEngineView>
#include <QtWebChannel>

3.从QObjec派生一个类

class WebClass : public QObject
{
    Q_OBJECT
public slots:
    void jscallme()
    {
        QMessageBox::information(NULL, "jscallme", "jscallme");
    }
};

MainWindow的类里声明变量

    QWebEngineView *webView = nullptr;
    QWebChannel *webChannel = nullptr;

MainWindow.cpp里初始化变量

    webView = new QWebEngineView(parent);
    webView->load(QUrl::fromLocalFile("D:\\Code\\EChartTest\\test.html"));
    mainLayout->addWidget(webView);
    webChannel = new QWebChannel;
    WebClass *webobj = new WebClass();
    webChannel->registerObject("webobj", webobj);
    webView->page()->setWebChannel(webChannel);

4.用文本编辑器新建一个test.html文件,内容写:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title></title>
</head>
<body>
  <script src="qwebchannel.js"></script> 
  <script type="text/javascript">
  new QWebChannel(qt.webChannelTransport,
  function(channel){
  var webobj = channel.objects.webobj;
  window.foo = webobj;
  webobj.jscallme();
  });
  </script>
</body>
</html>

5.将Qt目录"C:\Qt\Qt5.12.1\Examples\Qt-5.12.1\webchannel\shared"下的qwebchannel.js文件拷贝到上面的test.html目录下
6.好了,Qt端 运行程序。
7.结果为HTML的程序调用了C++的函数。

JS传递给C++

再进一步吧/
1.修改
void jscallme()

void jscallme(const QString &text)
{
    QMessageBox::information(NULL, "jscallme", text);
}

2.HTML端修改webobj.jscallme();webobj.jscallme('中文调用');
3.右键点击下Qt端的程序,reload后,弹出结果
4.每次都这样通过C++端函数赋值太麻烦了,可以直接在JS里给C++端变量赋值就好了。也简单,修改派生的类。

class WebClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString content MEMBER m_content)
public slots:
    void jscallme()
    {
        QMessageBox::information(NULL, "jscallme", m_content);
    }

private:
    QString m_content;
}

5.修改HTML端

  new QWebChannel(qt.webChannelTransport,
  function(channel){
  var webobj = channel.objects.webobj;
  window.foo = webobj;
  webobj.content = 'sdfef中文';
  webobj.jscallme();
  });

6.reload下Qt端程序,结果符合预期

c++传递到JS

1.修改派生类

 Q_PROPERTY(QString content MEMBER m_content NOTIFY contentChanged)

2.修改HTML端

  <script type="text/javascript">

var updateattribute=function(text)
{	
	document.write(text);	
}

  new QWebChannel(qt.webChannelTransport,
  function(channel){
  var webobj = channel.objects.webobj;
  window.foo = webobj;
  webobj.contentChanged.connect(updateattribute);

  });

  
  </script>

3.Qt程序上放个按钮,按钮按下事件里写:
webobj->setProperty("content", "453453453");
4.Qt程序上的webview会刷新出结果.

传递自定义结构数据

上面的例子里都是传递基本类型,如果我自己定义的数据类型怎么办呢?比如

struct Data
{
    int a;
    double b;
    QString str;
};

可惜花了一整天也没搞清楚怎么传递这样的结构,各种宏绕的头晕,有明白的同学请留言指教。
不过我却发现了通过QJsonObject来传递的简单方法,将上面的结构用QJSonObject重写就可以了,具体代码如下
Qt端类声明

class WebClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QJsonObject jsonData MEMBER m_jsonData NOTIFY dataChanged)
public:
signals:

    void dataChanged(const QJsonObject &jsonData);
private:
    QJsonObject m_jsonData;
};

Qt端主函数

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    btn = new QPushButton("..");
    connect(btn, &QPushButton::clicked, this,
            [&]()
    {
        QJsonObject json;
		json["a"] = 2;
        json["b"] = 3.336;
        json["c"] = "sdef";
        webobj->setProperty("jsonData", json);
    });
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(btn, 1, Qt::AlignLeft);

    webView = new QWebEngineView(parent);
    webView->load(QUrl::fromLocalFile("D:\\Code\\JS\\test.html"));
    layout->addWidget(webView);
    QWidget *w = new QWidget;
    w->setLayout(layout);

    setCentralWidget(w);

    webChannel = new QWebChannel;
    webobj = new WebClass();
    webChannel->registerObject("webobj", webobj);
    webView->page()->setWebChannel(webChannel);
    setMinimumSize(800, 600);
}

HTML端代码如下

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="utf-8">
    <!-- 引入 ECharts 文件 -->
    <script src="D:/Code/JS/Echart/echarts.min.js"></script>
</head>
<p id="x">x:</p>
<p id="y">y:</p>
<body>
    <script src="qwebchannel.js"></script>
    <script type="text/javascript">
       
        new QWebChannel(qt.webChannelTransport, function (channel) {
                var webobj = channel.objects.webobj;
             
                webobj.dataChanged.connect(function (arg) { 
                    x.innerHTML = "x:" + arg.x ;
                    y.innerHTML = "y:" + arg.y.toFixed(4);
                });

            });
    </script>
    
</body>

</html>

好了,自定义结构传递效果如下
GI2F.gif

更进一步

在下一步里直接用Qt生成随机数,通过QWebChannel发送到JS端,调用echarts控件显示曲线。
Qt调用Echarts显示动态过程曲线

参考文献

Communication between C++ and Javascript in Qt WebEngine

  • 47
    点赞
  • 246
    收藏
    觉得还不错? 一键收藏
  • 43
    评论
Qt是一款跨平台的C++图形用户界面应用程序开发框架,能够轻松开发高质量的跨平台应用程序。而百度地图是目前国内最流行的Web地图服务,为开发者提供了非常便捷的地图展示、位置检索、路线规划等能力。在Qt中使用百度地图,并能够与js交互,可以大大拓宽了应用的功能。 我们可以使用Qt Quick的WebView来实现百度地图的加载,同时也能够在WebView中嵌入JavaScript代码,实现和地图的互动。在Qt Quick中,可以使用QtWebView模块的WebEngineViewWebEngineViewExperimental类型的对象加载Web页面,并进行动态链接库的调用,从而实现与JavaScript的交互。 具体步骤如下: 1. 首先,在Qt Creator中创建一个Qt Quick项目,并在QML文件中加入一个WebView组件,用于加载百度地图。 2. 在C++代码中调用WebEngineViewWebEngineViewExperimental类型的对象,通过setUrl()方法加载百度地图的URL。 3. 通过WebView对象的runJavaScript()方法,在QML文件中嵌入JavaScript代码,并获取、设置百度地图中的特定属性或事件。 例如,我们可以在JavaScript中调用百度地图的JavaScript API,获取当前地图的中心点、缩放级别、添加标记、绘制图形等动作,从而实现和地图的交互。 总之,QtWebEngineView提供了非常便捷的方法来在Qt应用中加载Web页面,并与JavaScript进行交互,因此,我们可以使用它轻松地实现与百度地图的交互,为我们的应用程序增加更多的功能和乐趣。
评论 43
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值