《Qt C++混合编程 (1) Qt通过QWebengineView显示web页面》
《Qt C++混合编程 (2) Qt通过QWebEngineView与JS交互》
在客户端程序中,如果想实现web端那种炫酷大屏,数据可视化或者首页统计等功能,一般是比较难的。比如想实现下面这种效果:
但是换个思路,如果我们能把web嵌入到客户端并能实现双方的数据交互,那么也不失为一种好办法。
首先看实现效果,点击mainwindow的菜单,显示web页(qt调用js),然后点击饼图的某一块,qt中弹提示框(js调用qt)。
通过上一篇《Qt通过QWebengineView显示web页面》我们知道在Qt中可以通过QWebengineView来展示web,有了展示web的容器后,本篇看如何Qt和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)
//和Qt交互部分
new QWebChannel(qt.webChannelTransport, function(channel) {
window.bridge = channel.objects.bridge_name;
})
//开始调用C++中函数,showMsgBox为槽函数
if(bridge){
bridge.showMsgBox(params.name);
}
这部分其实是写在java script里面的,后面会在说明。
这个类继承至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进行通信的数据通道
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));
}
<!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>