Qt C++混合编程 (2) Qt通过QWebEngineView与JS交互

《Qt C++混合编程 (1) Qt通过QWebengineView显示web页面》
《Qt C++混合编程 (2) Qt通过QWebEngineView与JS交互》

一、背景

在客户端程序中,如果想实现web端那种炫酷大屏,数据可视化或者首页统计等功能,一般是比较难的。比如想实现下面这种效果:
Qt C++混合编程 (2) Qt通过QWebEngineView与JS交互_第1张图片Qt C++混合编程 (2) Qt通过QWebEngineView与JS交互_第2张图片
但是换个思路,如果我们能把web嵌入到客户端并能实现双方的数据交互,那么也不失为一种好办法。
首先看实现效果,点击mainwindow的菜单,显示web页(qt调用js),然后点击饼图的某一块,qt中弹提示框(js调用qt)。
Qt C++混合编程 (2) Qt通过QWebEngineView与JS交互_第3张图片

二、方法

1. 开始

通过上一篇《Qt通过QWebengineView显示web页面》我们知道在Qt中可以通过QWebengineView来展示web,有了展示web的容器后,本篇看如何Qt和js进行交互,其实都很简单。

  • C++调用js很简单
    m_view->page()->runJavaScript(QString("showPie(%1)").arg(sHtml));

runJavaScript是QWebEnginePage类的成员函数,只能说Qt考虑的很全面,直接调用方法就可以了。一共有4个重载,详细请看qt助手。

void QWebEnginePage::runJavaScript(const QString &scriptSource)
void QWebEnginePage::runJavaScript(const QString &scriptSource, const QWebEngineCallback<const QVariant &> &resultCallback)
void QWebEnginePage::runJavaScript(const QString &scriptSource, quint32 worldId)
void QWebEnginePage::runJavaScript(const QString &scriptSource, quint32 worldId, const QWebEngineCallback<const QVariant &> &resultCallback)
  • js调用C++函数
//和Qt交互部分
new QWebChannel(qt.webChannelTransport, function(channel) {
        window.bridge = channel.objects.bridge_name;
      })
//开始调用C++中函数,showMsgBox为槽函数
    if(bridge){
         bridge.showMsgBox(params.name);
     }

这部分其实是写在java script里面的,后面会在说明。

2. 新建bridge类

这个类继承至QObject,看名字应该知道是qt和js交互的类,桥梁。

#ifndef BRIDGE_H
#define BRIDGE_H

#include 

class bridge : public QObject
{
    Q_OBJECT
public:
    explicit bridge(QObject *parent = nullptr);

public slots:
    void showMsgBox(QString msg);//申明槽函数,供js调用
};

#endif // BRIDGE_H

#include "bridge.h"
#include 
#include 

bridge::bridge(QObject *parent) : QObject(parent)
{

}

void bridge::showMsgBox(QString msg)
{
    QMessageBox::information(nullptr, "123", msg);
}

mainWindow.h中定义:

    QWebEngineView* m_view;        //显示web的容器 
    QWebChannel* m_channel;         //和web进行通信的数据通道

3. 添加mainWindow c++代码

mainWindow构造函数中

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_view = new QWebEngineView(this);
    setCentralWidget(m_view);
    m_channel = new QWebChannel(this);          //创建通道对象用于和JS交互
    bridge *myBridge = new bridge;              //创建通道对象用于和JS交互
    m_channel->registerObject("mybridge", (QObject*)myBridge);// 这里注册对象名"mybridge"需要与JS函数用到的名称一致
    m_view->page()->setWebChannel(m_channel);

    QString htmlPath = QApplication::applicationDirPath() + "/index.html";
    m_view->page()->load("file:///" + htmlPath);
}

菜单响应函数中,首先拼接html/js代码,然后runJavaScript函数调用,最终显示图表。

void MainWindow::on_actionPie_triggered()
{
    QString sHtml =
            "\
            option={\
            title:{\
            text:'饼图程序调用高亮示例',\
            left:'center'\
            },\
            tooltip:{\
            trigger:'item',\
            formatter:'{a}
{b}:{c}({d}%)'\ },\ legend:{\ orient:'vertical',\ left:'left',\ data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']\ },\ series:[\ {\ name:'访问来源',\ type:'pie',\ radius:'55%',\ center:['50%','60%'],\ data:[\ {value:335,name:'直接访问'},\ {value:310,name:'邮件营销'},\ {value:234,name:'联盟广告'},\ {value:135,name:'视频广告'},\ {value:1548,name:'搜索引擎'}\ ],\ emphasis:{\ itemStyle:{\ shadowBlur:10,\ shadowOffsetX:0,\ shadowColor:'rgba(0,0,0,0.5)'\ }\ }\ }\ ]\ }\ "
; m_view->page()->runJavaScript(QString("showPie(%1)").arg(sHtml)); }

4. index.html代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>ECharts</title>
    <!-- 引入 echarts.js -->
    <script src="./echarts.min.js"></script>
	<script src="./qwebchannel.js"></script>
</head>
<body>
    <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
    <div id="main" style="width: 600px;height:400px;"></div>
    <script type="text/javascript">

//echarts部分,基于准备好的dom,初始化echarts实例     
var myChart = echarts.init(document.getElementById('main'));

//和Qt交互部分
new QWebChannel(qt.webChannelTransport, function(channel) {
        window.bridge = channel.objects.mybridge;
      })
	  
function showPie(option){
	if (option && typeof option === 'object') {
    myChart.setOption(option);
	//添加echarts点击事件,在点击事件中调用C++函数
	myChart.on('click', function(params){
		//alert(params.name);
		//开始调用C++中函数
		if(bridge){
			bridge.showMsgBox(params.name);
		}
	});
	}
}
    </script>
</body>
</html>

5.说明

  1. qwebchannel.js可以在qt官网下载,官方支持https://doc.qt.io/archives/qt-5.9/qtwebengine-webenginewidgets-markdowneditor-resources-qwebchannel-js.html
  2. html中用到的echarts,显示饼图。只是为了增加视觉效果,并不是本篇qt-js交互的重点。O(∩_∩)O哈哈~
    echarts官网:https://echarts.apache.org/zh/index.html
  3. 本文中的源码下载地址:https://gitee.com/zypapa100/myWeb

你可能感兴趣的:(Qt,c++开发实战,qt,js)