若该文为原创文章,转载请注明原文出处
本文章博客地址:https://hpzwl.blog.csdn.net/article/details/125731144

红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)

Qt开发专栏:三方库开发技术

上一篇:《Qt+ECharts开发笔记(二):Qt窗口动态调整大小,使ECharts跟随Qt窗口大小变换而变换大小》
下一篇:《Qt+ECharts开发笔记(四):ECharts的饼图介绍、基础使用和Qt封装百分比图Demo》

前言

  上一篇成功是EChart随着Qt窗口变化而变化,本篇将开始正式介绍柱状图介绍、基础使用,并将其封装一层Qt。
  本篇的demo实现了隐藏js代码的方式,实现了一个条形图的基本交互方式,即Qt调用js脚本操作html。

Demo演示

  

ECharts调试工具

  ECharts提供的纯JS代码编辑开发调试工具,可编辑js,并且查看运行效果:
  https://echarts.apache.org/examples/zh/editor.html
  
  开发过程中对于属性的查询和调试ECharts也提供了配置帮助。
  官方配置手册:https://echarts.apache.org/zh/option.html
  

目标

  随便找一个预期目标:
  

ECharts接口静态方式

  使用EChart调试工具开发,先调试出基础框架。
  这里贴出的全部代码:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>ECharts</title><!-- 引入刚刚下载的 ECharts 文件 --><!--<script src="echarts.js"></script>--><script src="./echarts.js"></script><!--<script src="D:/qtProject/echartsDemo/echartsDemo/modules/barEChartWidget/html/echarts.js"></script>--><!--<script src="echarts.min.js"></script>--><!--<script src="./echarts.min.js"></script>--><!--<script src="./html/echarts.min.js"></script>--><!--<script src="D:/qtProject/echartsDemo/echartsDemo/modules/barEChartWidget/html/echarts.min.js"></script>--></head><body><!--设置body跟随查u哪个口,main填充body--><style>#main,html,body{width: 100%;height: 100%;overflow: hidden;}#main {width: 100%;height: 100%;}</style><div id="main"></div><script type="text/javascript">// 基于准备好的dom,初始化echarts实例var myChart = echarts.init(document.getElementById('main'));// 窗口高度变化设置window.onresize = function() {myChart.resize();};// 指定图表的配置项和数据var option = {title: {text: 'ECharts 入门示例'},tooltip: {},legend: {data: ['销量']},xAxis: {data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']},yAxis: {},series: [{name: '销量',type: 'bar',data: [5, 20, 36, 10, 10, 20]}]};// 使用刚指定的配置项和数据显示图表。myChart.setOption(option);function initJs() {var myChart = echarts.init(document.getElementById('main'));var option;option = {tooltip: {trigger: 'axis'},grid: {left: '3%',right: '4%',bottom: '50',containLabel: true},legend: {orient: 'horizontal',x: 'center',y: 'bottom',itemGap: 100},xAxis: {type: 'value'},yAxis: {type: 'category',data: ['项目1', '项目2', '项目3']},series: [{name: '变量1',type: 'bar',stack: 'totla',label: {show: true},data: [11, 12, 13]},{name: '子项目1',type: 'bar',stack: 'totla',label: {show: true},data: [24, 20, 21]},{name: '变量3',type: 'bar',stack: 'totla',label: {show: true},data: [95, 87, 55]}]};};initJs();</script></body>
</html>

ECharts接口动态方式

  动态方式,最初目的是为了动态实现数据的js操作,在开发过程中发现动态方式还能隐藏echarts代码,使echarts代码不被抓取,最后决定全部改为动态加载方式。

步骤一:修改html

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>ECharts</title><script src="./echarts.js"></script></head><body><style>#main,html,body{width: 100%;height: 100%;overflow: hidden;}#main {width: 95%;height: 95%;}</style><div id="main"></div><script type="text/javascript">var myChart = echarts.init(document.getElementById('main'));window.onresize = function() {myChart.resize();};</script></body>
</html>

步骤二:初始化

  新增了loadFinished信号槽关联。

void BarEChartWidget::initControl()
{_pWebEngineView = new QWebEngineView(this);_pWebEnginePage = new QWebEnginePage(this);_pWebChannel = new QWebChannel(this);QString filePath;
#if 1filePath = QString("%1/%2").arg(_htmlDir).arg(_indexFileName);
#elsefilePath = "qrc:/barEChartWidget/html/barEChartWidget.html";
#endifLOG << "file exist:" << QFile::exists(filePath) << filePath;
#if 0// 打印html文件内容QFile file(_indexFilePath);file.open(QIODevice::ReadOnly);LOG << QString(file.readAll());file.close();
#endifconnect(_pWebEnginePage, SIGNAL(loadFinished(bool)), this, SLOT(slot_loadFinished(bool)));_pWebEnginePage->load(QUrl(filePath));_pWebEnginePage->setWebChannel(_pWebChannel);_pWebEngineView->setPage(_pWebEnginePage);// 背景透明
//    _pWebEngineView->setStyleSheet("background-color: transparent");_pWebEnginePage->setBackgroundColor(Qt::transparent);
}

步骤三:加载完成页面后进行初始化

void BarEChartWidget::slot_loadFinished(bool result)
{if(result){initJs();}
}
void BarEChartWidget::initJs()
{_initJsStr = QSTRING("var option;""option = {""    tooltip: {""        trigger: 'axis'""    },""    grid: {""        left: '10',""        right: '10',""        top: '10',""        bottom: 30,""        containLabel: true""    },""    legend: {""        orient: 'horizontal',""        x: 'center',""        y: 'bottom',""        itemGap: 20""    },""    xAxis: {""        type: 'value'""    },""    yAxis: {""        type: 'category',""        data: ['项目1', '项目2', '项目3']""    },""    series: [""        {""            name: '变量1',""            type: 'bar',""            stack: 'totla',""            label: {""                show: true""            },""            data: [11, 12, 13]""        },""        {""            name: '变量2',""            type: 'bar',""            stack: 'totla',""            label: {""                show: true""            },""            data: [24, 20, 21]""        },""        {""            name: '变量3',""            type: 'bar',""            stack: 'totla',""            label: {""                show: true""            },""            data: [95, 87, 55]""        }""    ]""};""myChart.setOption(option);");runJsScript(_initJsStr);
}void BarEChartWidget::runJsScript(QString str)
{if(_pWebEnginePage){_pWebEnginePage->runJavaScript(str);}
}

步骤四:动态执行js操作

重置

void BarEChartWidget::on_pushButton_reset_clicked()
{initJs();
}

刷新

void BarEChartWidget::on_pushButton_flush_clicked()
{QString jsStr ="var empty = {};""myChart.setOption(empty, true);""myChart.setOption(option, true);";runJsScript(jsStr);
}

清空

void BarEChartWidget::on_pushButton_clear_clicked()
{QString jsStr ="option.series[0].data = [];""option.series[1].data = [];""option.series[2].data = [];""myChart.setOption(option, true);";runJsScript(jsStr);
}

随机生成(使用js代码)

void BarEChartWidget::on_pushButton_createRandom_clicked()
{QString jsStr ="var min = 0;""var max = 100;""for(var i = 0; i < option.series.length; i++)""{""    for(var j = 0; j < option.yAxis.data.length; j++)""    {""        option.series[i].data[j] = Math.floor(Math.random() * (max - min)) + min;""    }""}""myChart.setOption(option, true);";runJsScript(jsStr);
}

  后续用会将数据进行Qt的一份缓存数据,由Qt的数据去生成ecahrts的js脚本。

Demo

html文件

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>ECharts</title><script src="./echarts.js"></script></head><body><style>#main,html,body{width: 100%;height: 100%;overflow: hidden;}#main {width: 95%;height: 95%;}</style><div id="main"></div><script type="text/javascript">var myChart = echarts.init(document.getElementById('main'));window.onresize = function() {myChart.resize();};</script></body>
</html>

  在代码中使用js初始化echarts:
BarECartWidget.h

#ifndef BARECHARTWIDGET_H
#define BARECHARTWIDGET_H#include <QWidget>
#include <QWebEngineView>
#include <QWebEnginePage>
#include <QWebChannel>namespace Ui {class BarEChartWidget;
}class BarEChartWidget : public QWidget
{Q_OBJECTpublic:explicit BarEChartWidget(QWidget *parent = 0);~BarEChartWidget();protected:void initControl();protected slots:void slot_loadFinished(bool result);protected:void initJs();protected:void runJsScript(QString str);protected:void resizeEvent(QResizeEvent *event);private slots:void on_pushButton_clear_clicked();void on_pushButton_flush_clicked();void on_pushButton_createRandom_clicked();void on_pushButton_reset_clicked();private:Ui::BarEChartWidget *ui;private:QWebEngineView *_pWebEngineView;            // 浏览器窗口QWebEnginePage *_pWebEnginePage;            // 浏览器页面QWebChannel *_pWebChannel;                  // 浏览器js交互QString _htmlDir;                           // html文件夹路径QString _indexFileName;                     // html文件QString _initJsStr;                         // 第一次初始化的表格
};#endif // BARECHARTWIDGET_H

BarEChartWidget.cpp

#include "BarEChartWidget.h"
#include "ui_BarEChartWidget.h"#include <QFile>
#include <QMessageBox>
#include <QTimer>// QtCreator在msvc下设置编码也或有一些乱码,直接一刀切,避免繁琐的设置
//#define MSVC
#ifdef MSVC
#define QSTRING(s)  QString::fromLocal8Bit(s)
#else
#define QSTRING(s)  QString(s)
#endif#include <QDebug>
#include <QDateTime>
//#define LOG qDebug()<<__FILE__<<__LINE__
//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__
//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()
//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")
#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")BarEChartWidget::BarEChartWidget(QWidget *parent) :QWidget(parent),ui(new Ui::BarEChartWidget),_pWebEngineView(0),_pWebEnginePage(0),_pWebChannel(0),_htmlDir("D:/qtProject/echartsDemo/echartsDemo/modules/barEChartWidget/html"),    // 使用了绝对路径,引到html文件夹_indexFileName("barEChartWidget.html")
{ui->setupUi(this);QString version = "v1.0.0";setWindowTitle(QString("基于Qt的ECharts条状图Demo %1(长沙红胖子 QQ:21497936 WX:15173255813 blog:hpzwl.blog.csdn.net").arg(version));// 设置无边框,以及背景透明// 背景透明,在界面构架时,若为本窗口为其他窗口提升为本窗口时,// 则再qss会在主窗口第一级添加frame_all,防止其他窗口提升本窗口而冲掉qss设置
//    setWindowFlag(Qt::FramelessWindowHint);
//    setAttribute(Qt::WA_TranslucentBackground, true);#if 0// 这是方法一:让滚动条不出来(通过大小),还有一个方法是在html设置body的overflow: hidden
//    resize(600 + 20, 400 + 20);
#endifinitControl();
}BarEChartWidget::~BarEChartWidget()
{delete ui;
}void BarEChartWidget::initControl()
{_pWebEngineView = new QWebEngineView(this);_pWebEnginePage = new QWebEnginePage(this);_pWebChannel = new QWebChannel(this);QString filePath;
#if 1filePath = QString("%1/%2").arg(_htmlDir).arg(_indexFileName);
#elsefilePath = "qrc:/barEChartWidget/html/barEChartWidget.html";
#endifLOG << "file exist:" << QFile::exists(filePath) << filePath;
#if 0// 打印html文件内容QFile file(_indexFilePath);file.open(QIODevice::ReadOnly);LOG << QString(file.readAll());file.close();
#endifconnect(_pWebEnginePage, SIGNAL(loadFinished(bool)), this, SLOT(slot_loadFinished(bool)));_pWebEnginePage->load(QUrl(filePath));_pWebEnginePage->setWebChannel(_pWebChannel);_pWebEngineView->setPage(_pWebEnginePage);// 背景透明
//    _pWebEngineView->setStyleSheet("background-color: transparent");_pWebEnginePage->setBackgroundColor(Qt::transparent);
}void BarEChartWidget::slot_loadFinished(bool result)
{if(result){initJs();}
}void BarEChartWidget::initJs()
{_initJsStr = QSTRING("var option;""option = {""    tooltip: {""        trigger: 'axis'""    },""    grid: {""        left: '10',""        right: '10',""        top: '10',""        bottom: 30,""        containLabel: true""    },""    legend: {""        orient: 'horizontal',""        x: 'center',""        y: 'bottom',""        itemGap: 20""    },""    xAxis: {""        type: 'value'""    },""    yAxis: {""        type: 'category',""        data: ['项目1', '项目2', '项目3']""    },""    series: [""        {""            name: '变量1',""            type: 'bar',""            stack: 'totla',""            label: {""                show: true""            },""            data: [11, 12, 13]""        },""        {""            name: '变量2',""            type: 'bar',""            stack: 'totla',""            label: {""                show: true""            },""            data: [24, 20, 21]""        },""        {""            name: '变量3',""            type: 'bar',""            stack: 'totla',""            label: {""                show: true""            },""            data: [95, 87, 55]""        }""    ]""};""myChart.setOption(option);");runJsScript(_initJsStr);
}void BarEChartWidget::runJsScript(QString str)
{if(_pWebEnginePage){_pWebEnginePage->runJavaScript(str);}
}void BarEChartWidget::resizeEvent(QResizeEvent *event)
{if(_pWebEngineView){_pWebEngineView->setGeometry(ui->label_echarts->geometry());}
}void BarEChartWidget::on_pushButton_clear_clicked()
{QString jsStr ="option.series[0].data = [];""option.series[1].data = [];""option.series[2].data = [];""myChart.setOption(option, true);";runJsScript(jsStr);
}void BarEChartWidget::on_pushButton_flush_clicked()
{QString jsStr ="var empty = {};""myChart.setOption(empty, true);""myChart.setOption(option, true);";runJsScript(jsStr);
}void BarEChartWidget::on_pushButton_createRandom_clicked()
{QString jsStr ="var min = 0;""var max = 100;""for(var i = 0; i < option.series.length; i++)""{""    for(var j = 0; j < option.yAxis.data.length; j++)""    {""        option.series[i].data[j] = Math.floor(Math.random() * (max - min)) + min;""    }""}""myChart.setOption(option, true);";runJsScript(jsStr);
}void BarEChartWidget::on_pushButton_reset_clicked()
{initJs();
}

入坑

入坑一:调用js函数失败

问题

  通过qt代码跑js调用函数失败。
  

  

原理

  先要等页面加载完成后才能调用定义的函数。

解决

  发现是调用成功了,原来只定义也会报这个错误。
  
  由此可以看出,在qt中去初始化需要等待页面加载完成才行。

入坑二:Qt的msvc编译器少数中文乱码

问题

  少数中文乱码,加空格等都无法解决。
  

解决

  最终解决了,尝试了QTextCodec等各种都不行,最终:
  
  

工程模板v1.2.0

  

后话

  条形图将会根据实际需求持续升级版本,下一篇会介绍饼图的基本使用以及Qt封装的百分比饼图Demo。

上一篇:《Qt+ECharts开发笔记(二):Qt窗口动态调整大小,使ECharts跟随Qt窗口大小变换而变换大小》
下一篇:《Qt+ECharts开发笔记(四):ECharts的饼图介绍、基础使用和Qt封装百分比图Demo》

若该文为原创文章,转载请注明原文出处
本文章博客地址:https://hpzwl.blog.csdn.net/article/details/125731144

Qt+ECharts开发笔记(三):ECharts的柱状图介绍、基础使用和Qt封装Demo相关推荐

  1. Qt+ECharts开发笔记(五):ECharts的动态排序柱状图介绍、基础使用和Qt封装Demo

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/127171413 红胖子(红模仿)的博文大全:开发技术集 ...

  2. 开发笔记——vue echarts图表在切换页面大小时缩成一团

    开发笔记--vue echarts图表在切换页面大小时缩成一团 添加this.$nextTick() this.$nextTick(()=>{this.getjkechertsdata(); / ...

  3. Qt+QtWebApp开发笔记(一):QtWebApp介绍、下载和搭建基础封装http轻量级服务器Demo

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/130631547 红胖子网络科技博文大全:开发技术集合( ...

  4. vue3中,echarts使用(四)02——柱状图之堆叠条形图-定制化 封装切换tag标签组件 封装title组件

    vue3中,echarts使用(四)02--柱状图之堆叠条形图-定制化 & 封装切换tag标签组件 & 封装title组件 效果 代码 1.主页面 index.vue <temp ...

  5. 【Visual C++】游戏开发笔记三十七 浅墨DirectX提高班之五 顶点缓存的红颜知己 索引缓存的故事

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

  6. 【Visual C++】游戏开发笔记三十七 浅墨DirectX提高班之五 顶点缓存的红颜知己:索引缓存的故事

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8304741 作者:毛星云(浅墨 ...

  7. 【Vue ECharts开发】自定义echarts柱状图颜色渐变效果

    1. 效果演示 2. 示例代码 Vue 模板代码: <template><div><div id="main"></div>< ...

  8. 麒麟系统开发笔记(二):国产麒麟系统搭建Qt开发环境安装Qt5.12

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/123840699 红胖子(红模仿)的博文大全:开发技术集 ...

  9. JNI开发笔记(三)--JNI工程的框架分析

    JNI工程的框架分析 引 1. JNI工程的组成部分 2. 各个部分之间的关系 引 JNI开发笔记(一)–Android Studio安装与环境搭建 JNI开发笔记(二)–创建JNI基础工程并运行 1 ...

  10. 【Visual C++】游戏开发笔记三十四 浅墨DirectX提高班之三 起承转合的艺术:Direct3D渲染五步曲...

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8223965 作者:毛星云(浅墨 ...

最新文章

  1. MySQL数据库性能优化之一
  2. 刘涵 美国 西北大学 计算机,西北大学关于表彰2010-2011学年度学生先进集体-红帆.doc...
  3. Apache+php5
  4. Standard Template Library标准模板库专项复习总结(一)
  5. java 实例的生命周期_[Java教程]Vue实例生命周期
  6. 床笠行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  7. activemq高可用
  8. java 事件处理机制
  9. JS编程练习题(javascript)
  10. 修改电脑微信提示音+dll文件编辑器
  11. 4r照片尺寸是多大_4寸照片尺寸多少厘米 多少像素
  12. 机器学习:概念学习FIND-S算法C++实现
  13. 在Android上模拟登录广工正方教务系统查询成绩
  14. [完全版] Windows安装与配置Git cz (commitizen)
  15. 观察 | 经济学诺奖的启示:金融科技的核心任务是什么?
  16. m个苹果放在n个筐里,每个筐至少一个,所有的筐都一样,有多少种放法
  17. 第九节-python函数介绍(中)
  18. 服务器原装的系统怎么格式化,怎么将云服务器系统格式化
  19. 员工被提拔,还是被干掉,就看这3点......
  20. 年末放大招,Java进阶大数据3W全套视频免费领!

热门文章

  1. 使用Javascript动态添加和删除元素
  2. 电脑上怎么批量压缩图片?如何快速批量压缩图片?
  3. 塔米狗上的达人名片有什么作用?
  4. Gossip 协议详解
  5. 【操作系统】CPU调度算法
  6. 小鸡模拟器显示无法连接服务器,小鸡模拟器安装不了怎么办
  7. C++ atuo关键字的应用 -- 尾置返回类型(trailing return type)
  8. 华为p9总显示切换服务器中,怎么更改华为p9的多任务切换 | 手游网游页游攻略大全...
  9. Qt之小学徒学习记录分享
  10. 不需要死记硬背,看一遍就能记住单词的意思,一起了解单词背后的有趣故事(6)