QML WebEngine + ECharts展示实时曲线

(相信不少人都会用 ECharts 这个网页图表库,我这里也只是学 WebEngine 顺带做个笔记)

我的环境:Qt5.15.1 MSVC 32bit,不同的版本可能 webengine 的初始化有所不同,以官方文档为准。

本文完整项目链接:https://github.com/gongjianbo/MyTestCode/tree/master/Qml/QmlWebEngineECharts

0.下载ECharts

下载地址:https://echarts.apache.org/zh/download.html

提供了三种方式的下载:

方法一:从下载的源代码或编译产物安装

方法二:从 npm 安装

方法三:选择需要的模块,在线定制下载

这里我选择的定制下载:https://echarts.apache.org/zh/builder.html ,选择自己所需模块后就可以下载单个 js 文件。

1.QML WebEngine使用ECharts

WebEngine 初始化步骤参照文档:https://doc.qt.io/qt-5/qml-qtwebengine-webengineview.html

pro 文件加上 webengine 模块:

QT += webengine
   
   

main.cpp 文件初始化 webengine 相关:


   
   
  1. //#include <qtwebengineglobal.h>
  2. // 因为5.13的在线文档没了,所以我没法判断,请自己查下文档
  3. #if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
  4. QCoreApplication:: setAttribute(Qt::AA_ShareOpenGLContexts);
  5. // 有些情况可能需要soft opengl
  6. QCoreApplication:: setAttribute(Qt::AA_UseSoftwareOpenGL);
  7. // webengine须初始化,5.12放在app构造后,5.15放在构造前
  8. QtWebEngine:: initialize();
  9. QGuiApplication app(argc, argv);
  10. #else
  11. // 5.12提示Attribute Qt::AA_ShareOpenGLContexts must be set before QCoreApplication is created
  12. QCoreApplication:: setAttribute(Qt::AA_ShareOpenGLContexts);
  13. // 有些情况可能需要soft opengl
  14. //QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
  15. // webengine须初始化,5.12放在app构造后,5.15放在构造前
  16. QGuiApplication app(argc, argv);
  17. QtWebEngine:: initialize();
  18. #endif

从 ECharts 的官方示例拷贝实时曲线的例程:https://echarts.apache.org/examples/zh/editor.html?c=dynamic-data2

将例程放到 html 文件中,参照:ECharts官方教程 ,由于比较长,我就放到下一节以及 github 链接了(我把 echarts.js 和 index.html 放在了单独的文件夹,pro DESTDIR 也指定到了该目录)。

最后把 qml 文件改改就能运行了:


   
   
  1. import QtQuick 2.12
  2. import QtQuick. Window 2.12
  3. import QtWebEngine 1.2
  4. Window {
  5. width: 640
  6. height: 480
  7. visible: true
  8. title: qsTr( "WebEngine + ECharts (By: GongJianBo1992)")
  9. WebEngineView{
  10. anchors. fill: parent
  11. //@disable-check M7
  12. url: "file:///./index.html"
  13. }
  14. }

尽量用 release 跑, debug 模式很容易崩溃。还有就是有些环境可能需要设置 AA_UseSoftwareOpenGL 才能正常运行,但是这又导致持续动态刷新很占 cpu。

2.传递数据到 html ,实时刷新曲线

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


   
   
  1. import QtQuick 2.12
  2. import QtQuick. Window 2.12
  3. import QtQuick. Controls 2.12
  4. import QtWebEngine 1.2
  5. Window {
  6. id: root
  7. width: 640
  8. height: 480
  9. visible: true
  10. title: qsTr( "WebEngine + ECharts (By: GongJianBo1992)")
  11. property var now: new Date( 1997, 9, 3)
  12. property var oneDay: 24 * 3600 * 1000
  13. WebEngineView{
  14. id: view
  15. anchors. fill: parent
  16. //@disable-check M7
  17. url: "file:///./index.html"
  18. }
  19. Row{
  20. anchors. right: parent. right
  21. anchors. top: parent. top
  22. anchors. margins: 10
  23. spacing: 10
  24. Button{
  25. text: "单个数据"
  26. onClicked: {
  27. now = new Date(+now + oneDay);
  28. view. runJavaScript( "window.appendData("+
  29. JSON. stringify({
  30. "date":now. valueOf(),
  31. "value": Number( Math. random() * 1000 + 500)
  32. })+ ")");
  33. }
  34. }
  35. Button{
  36. text: "批量数据"
  37. onClicked: {
  38. let datalist=[];
  39. for( let i= 0;i< 100;i++)
  40. {
  41. now = new Date(+now + oneDay);
  42. datalist. push({ "date":now. valueOf(), "value": Number( Math. random() * 1000 + 500)});
  43. }
  44. view. runJavaScript( "window.setData("+
  45. JSON. stringify(datalist)+ ")");
  46. }
  47. }
  48. }
  49. }

   
   
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Document </title>
  7. <style>
  8. html,
  9. body,
  10. #echarts {
  11. margin: 0px;
  12. padding: 0px;
  13. width: 100%;
  14. height: 100%;
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <div id="echarts"> </div>
  20. <!-- 引入 echarts -->
  21. <script src="./echarts.min.js"> </script>
  22. <script>
  23. //每次now+一天
  24. function randomData( ) {
  25. now = new Date(+now + oneDay);
  26. //name给标签用,value是x-y坐标点
  27. return {
  28. name: now. toString(),
  29. value: [now, Math. random() * 1000 + 500]
  30. };
  31. }
  32. //新的数据
  33. function newData( dataitem) {
  34. now = new Date(dataitem. date);
  35. return {
  36. name: now. toString(),
  37. value: [now, dataitem. value]
  38. };
  39. }
  40. var myChart = echarts. init( document. getElementById( 'echarts'));
  41. var data = [];
  42. var now = + new Date( 1970, 1, 1);
  43. var oneDay = 24 * 3600 * 1000;
  44. myChart. setOption({
  45. title: {
  46. text: '动态数据 + 时间坐标轴'
  47. },
  48. tooltip: {
  49. trigger: 'axis',
  50. formatter: function ( params) {
  51. params = params[ 0];
  52. var date = new Date(params. name);
  53. return date. getDate() + '/' + (date. getMonth() + 1) + '/' + date. getFullYear() + ' : ' +
  54. params. value[ 1];
  55. },
  56. axisPointer: {
  57. animation: false
  58. }
  59. },
  60. xAxis: {
  61. type: 'time',
  62. min: now - 100 * oneDay,
  63. max: now,
  64. splitLine: {
  65. show: false
  66. }
  67. },
  68. yAxis: {
  69. type: 'value',
  70. min: 0,
  71. max: 2000,
  72. boundaryGap: [ 0, '100%'],
  73. splitLine: {
  74. show: false
  75. }
  76. },
  77. series: [{
  78. name: '模拟数据',
  79. type: 'line',
  80. showSymbol: false,
  81. hoverAnimation: false,
  82. data: data
  83. }]
  84. });
  85. //刷新数据
  86. function updateData( ) {
  87. myChart. setOption({
  88. xAxis: {
  89. type: 'time',
  90. min: now - 100 * oneDay,
  91. max: now
  92. },
  93. series: [{
  94. data: data
  95. }]
  96. });
  97. }
  98. //定时填充数据
  99. //每次数据x加一天,范围为100天
  100. /*setInterval(function () {
  101. if (data.length > 100)
  102. data.shift();
  103. data.push(randomData());
  104. updateData();
  105. }, 200);*/
  106. //我们定义dataitem结构为[date,value]
  107. //添加单个数据
  108. function appendData( dataitem) {
  109. if (data. length > 100)
  110. data. shift();
  111. data. push( newData(dataitem));
  112. updateData();
  113. }
  114. //添加批量数据
  115. function setData( datalist) {
  116. if (datalist. length <= 0)
  117. return;
  118. while (datalist. length > 100)
  119. datalist. shift();
  120. data = [];
  121. for ( var i = 0; i < datalist. length; i++)
  122. data. push( newData(datalist[i]));
  123. updateData();
  124. }
  125. //自适应大小
  126. window. addEventListener( "resize", function ( ) {
  127. myChart. resize();
  128. });
  129. </script>
  130. </body>
  131. </html>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值