(相信不少人都会用 ECharts 这个网页图表库,我这里也只是学 WebEngine 顺带做个笔记)
我的环境:Qt5.15.1 MSVC 32bit,不同的版本可能 webengine 的初始化有所不同,以官方文档为准。
本文完整项目链接:https://github.com/gongjianbo/MyTestCode/tree/master/Qml/QmlWebEngineECharts
下载地址:https://echarts.apache.org/zh/download.html
提供了三种方式的下载:
方法一:从下载的源代码或编译产物安装
方法二:从 npm 安装
方法三:选择需要的模块,在线定制下载
这里我选择的定制下载:https://echarts.apache.org/zh/builder.html ,选择自己所需模块后就可以下载单个 js 文件。
WebEngine 初始化步骤参照文档:https://doc.qt.io/qt-5/qml-qtwebengine-webengineview.html
pro 文件加上 webengine 模块:
QT += webengine
main.cpp 文件初始化 webengine 相关:
-
//#include
-
// 因为5.13的在线文档没了,所以我没法判断,请自己查下文档
-
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
-
QCoreApplication::
setAttribute(Qt::AA_ShareOpenGLContexts);
-
// 有些情况可能需要soft opengl
-
QCoreApplication::
setAttribute(Qt::AA_UseSoftwareOpenGL);
-
// webengine须初始化,5.12放在app构造后,5.15放在构造前
-
QtWebEngine::
initialize();
-
QGuiApplication app(argc, argv);
-
#else
-
// 5.12提示Attribute Qt::AA_ShareOpenGLContexts must be set before QCoreApplication is created
-
QCoreApplication::
setAttribute(Qt::AA_ShareOpenGLContexts);
-
// 有些情况可能需要soft opengl
-
//QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
-
// webengine须初始化,5.12放在app构造后,5.15放在构造前
-
QGuiApplication app(argc, argv);
-
QtWebEngine::
initialize();
-
#endif
从 ECharts 的官方示例拷贝实时曲线的例程:https://echarts.apache.org/examples/zh/editor.html?c=dynamic-data2
将例程放到 html 文件中,参照:ECharts官方教程 ,由于比较长,我就放到下一节以及 github 链接了(我把 echarts.js 和 index.html 放在了单独的文件夹,pro DESTDIR 也指定到了该目录)。
最后把 qml 文件改改就能运行了:
-
import
QtQuick
2.12
-
import
QtQuick.
Window
2.12
-
import
QtWebEngine
1.2
-
-
Window {
-
width:
640
-
height:
480
-
visible:
true
-
title:
qsTr(
"WebEngine + ECharts (By: GongJianBo1992)")
-
-
WebEngineView{
-
anchors.
fill: parent
-
//@disable-check M7
-
url:
"file:///./index.html"
-
}
-
}
尽量用 release 跑, debug 模式很容易崩溃。还有就是有些环境可能需要设置 AA_UseSoftwareOpenGL 才能正常运行,但是这又导致持续动态刷新很占 cpu。
webengine 传递数据到 html 还是比较方便的,可以直接调用 js 函数传递参数,也可以用 websocket,或者 ajax 请求数据。这里我使用的调用 js 函数传递 JSON 参数。
webengineview 提供了 runJavaScript 函数在 web 中执行脚本:
void runJavaScript(string script, variant callback)
最终效果:
下面是 html 和 qml 的代码:
完整项目链接:https://github.com/gongjianbo/MyTestCode/tree/master/Qml/QmlWebEngineECharts
-
import
QtQuick
2.12
-
import
QtQuick.
Window
2.12
-
import
QtQuick.
Controls
2.12
-
import
QtWebEngine
1.2
-
-
Window {
-
id: root
-
width:
640
-
height:
480
-
visible:
true
-
title:
qsTr(
"WebEngine + ECharts (By: GongJianBo1992)")
-
property
var
now:
new
Date(
1997,
9,
3)
-
property
var
oneDay:
24 *
3600 *
1000
-
-
WebEngineView{
-
id: view
-
anchors.
fill: parent
-
//@disable-check M7
-
url:
"file:///./index.html"
-
}
-
-
Row{
-
anchors.
right: parent.
right
-
anchors.
top: parent.
top
-
anchors.
margins:
10
-
spacing:
10
-
-
Button{
-
text:
"单个数据"
-
onClicked: {
-
now =
new
Date(+now + oneDay);
-
view.
runJavaScript(
"window.appendData("+
-
JSON.
stringify({
-
"date":now.
valueOf(),
-
"value":
Number(
Math.
random() *
1000 +
500)
-
})+
")");
-
}
-
}
-
-
Button{
-
text:
"批量数据"
-
onClicked: {
-
let datalist=[];
-
for(
let i=
0;i<
100;i++)
-
{
-
now =
new
Date(+now + oneDay);
-
datalist.
push({
"date":now.
valueOf(),
"value":
Number(
Math.
random() *
1000 +
500)});
-
}
-
view.
runJavaScript(
"window.setData("+
-
JSON.
stringify(datalist)+
")");
-
}
-
}
-
}
-
}
-
html>
-
<html lang="en">
-
-
<head>
-
<meta charset="UTF-8">
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
<title>Document
title>
-
<style>
-
html,
-
body,
-
#echarts {
-
margin:
0px;
-
padding:
0px;
-
width:
100%;
-
height:
100%;
-
}
-
style>
-
head>
-
-
<body>
-
<div id="echarts">
div>
-
-
<script src="./echarts.min.js">
script>
-
<script>
-
//每次now+一天
-
function
randomData(
) {
-
now =
new
Date(+now + oneDay);
-
//name给标签用,value是x-y坐标点
-
return {
-
name: now.
toString(),
-
value: [now,
Math.
random() *
1000 +
500]
-
};
-
}
-
-
//新的数据
-
function
newData(
dataitem) {
-
now =
new
Date(dataitem.
date);
-
return {
-
name: now.
toString(),
-
value: [now, dataitem.
value]
-
};
-
}
-
-
var myChart = echarts.
init(
document.
getElementById(
'echarts'));
-
var data = [];
-
var now = +
new
Date(
1970,
1,
1);
-
var oneDay =
24 *
3600 *
1000;
-
-
myChart.
setOption({
-
title: {
-
text:
'动态数据 + 时间坐标轴'
-
},
-
tooltip: {
-
trigger:
'axis',
-
formatter:
function (
params) {
-
params = params[
0];
-
var date =
new
Date(params.
name);
-
return date.
getDate() +
'/' + (date.
getMonth() +
1) +
'/' + date.
getFullYear() +
' : ' +
-
params.
value[
1];
-
},
-
axisPointer: {
-
animation:
false
-
}
-
},
-
xAxis: {
-
type:
'time',
-
min: now -
100 * oneDay,
-
max: now,
-
splitLine: {
-
show:
false
-
}
-
},
-
yAxis: {
-
type:
'value',
-
min:
0,
-
max:
2000,
-
boundaryGap: [
0,
'100%'],
-
splitLine: {
-
show:
false
-
}
-
},
-
series: [{
-
name:
'模拟数据',
-
type:
'line',
-
showSymbol:
false,
-
hoverAnimation:
false,
-
data: data
-
}]
-
});
-
-
//刷新数据
-
function
updateData(
) {
-
myChart.
setOption({
-
xAxis: {
-
type:
'time',
-
min: now -
100 * oneDay,
-
max: now
-
},
-
series: [{
-
data: data
-
}]
-
});
-
}
-
-
//定时填充数据
-
//每次数据x加一天,范围为100天
-
/*setInterval(function () {
-
if (data.length > 100)
-
data.shift();
-
data.push(randomData());
-
-
updateData();
-
}, 200);*/
-
-
//我们定义dataitem结构为[date,value]
-
//添加单个数据
-
function
appendData(
dataitem) {
-
if (data.
length >
100)
-
data.
shift();
-
data.
push(
newData(dataitem));
-
-
updateData();
-
}
-
-
//添加批量数据
-
function
setData(
datalist) {
-
if (datalist.
length <=
0)
-
return;
-
while (datalist.
length >
100)
-
datalist.
shift();
-
data = [];
-
for (
var i =
0; i < datalist.
length; i++)
-
data.
push(
newData(datalist[i]));
-
-
updateData();
-
}
-
-
//自适应大小
-
window.
addEventListener(
"resize",
function (
) {
-
myChart.
resize();
-
});
-
script>
-
body>
-
-
html>