前言

  上一篇的demo使用隐藏js代码的方式,实现了一个饼图的基本交互方式,并预留了Qt模块对外的基础接口。
  本篇的demo实现了自动排序的柱状图,实现了一个自动排序柱状图的基本交互方式,即Qt调用js脚本操作html。
  本篇demo使用Qt定时器方式,实现数据定时刷新自增,并预留出了定时器间隔参数。
  像大数据网页常看的人口增长时间图,收入年度增长时间图等都是这一类。

 

Demo演示

  

 

ECharts代码效果调试

  使用ECharts的在线调试器,先调试出大致预期的效果。

option = {
xAxis: {
max: 'dataMax'
},
yAxis: {
type: 'category',
data: ['特斯拉', '奔驰', '宝马', '理想', '蔚来'],
inverse: true,
animationDuration: 300,
animationDurationUpdate: 300,
max: 4
},
series: [
{
realtimeSort: true,
name: 'X',
type: 'bar',
data: [10,20,50,10,30],
label: {
show: true,
position: 'right',
valueAnimation: true
},
itemStyle: {
color: function(params) {
var colorList = ['#EE14FF', '#F092FF', '#FF61FE', '#A02F99', '#F00682']; /* 注意1:需要分号 */
return colorList[params.dataIndex]; /* 注意2:需要dataIndex,获取序号 */
}
}
},
],
graphic: {
elements: [ /* 时间标志 */
{
type: 'text',
right: 160,
bottom: 100,
style: {
text: '1970-01',
font: 'bolder 100px monospace',
fill: 'rgba(100, 100, 100, 0.25)'
},
z: 100
}
]
},
legend: {
show: false,
},
animationDuration: 0,
animationDurationUpdate: 1000,
animationEasing: 'linear',
animationEasingUpdate: 'linear'
};

  

 

Qt封装动态ECharts

步骤一:静态html

  此系列的标准html文件,因为是标准的所以对文件名进行了调整,改为eChartWidget.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>

步骤二:初始化

void BarAutoSortEChartWidget::initControl()
{
_pWebEngineView = new QWebEngineView(this);
_pWebEnginePage = new QWebEnginePage(this);
_pWebChannel = new QWebChannel(this);
QString filePath;
#if 1
filePath = QString("%1/%2").arg(_htmlDir).arg(_indexFileName);
#else
filePath = "qrc:/barAutoSortEChartWidget/html/eChartWidget.html";
#endif
LOG << "file exist:" << QFile::exists(filePath) << filePath;
#if 0
// 打印html文件内容
QFile file(_indexFilePath);
file.open(QIODevice::ReadOnly);
LOG << QString(file.readAll());
file.close();
#endif
connect(_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 BarAutoSortEChartWidget::on_pushButton_reset_clicked()
{
initJs();
}

刷新

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

开始统计(使用Qt代码)

  这里预留了定时器间隔。

void BarAutoSortEChartWidget::on_pushButton_start_clicked()
{
if(_timerId == -1)
{
LOG << ui->lineEdit_interval->text().toInt();
_timerId = startTimer(ui->lineEdit_interval->text().toInt());
_dateTime.setSecsSinceEpoch(0);
QString jsStr = QString(
"option.series[0].data[0] = 0;"
"option.series[0].data[1] = 0;"
"option.series[0].data[2] = 0;"
"option.series[0].data[3] = 0;"
"option.series[0].data[4] = 0;"
"option.graphic.elements[0].style.text= '%1';"
"myChart.setOption(option, true);"
)
.arg(_dateTime.toString("yyyy-MM"));
runJsScript(jsStr); ui->pushButton_start->setText("停止统计");
}else{
if(_timerId != -1)
{
killTimer(_timerId);
_timerId = -1;
}
ui->pushButton_start->setText("开始统计");
}
}
void BarAutoSortEChartWidget::timerEvent(QTimerEvent *event)
{
_dateTime = _dateTime.addMonths(1);
if(_dateTime >= QDateTime::currentDateTime())
{
if(_timerId != -1)
{
killTimer(_timerId);
_timerId = -1;
}
}
QString jsStr = QString(
"option.series[0].data[0] = option.series[0].data[0] + %1;"
"option.series[0].data[1] = option.series[0].data[1] + %2;"
"option.series[0].data[2] = option.series[0].data[2] + %3;"
"option.series[0].data[3] = option.series[0].data[3] + %4;"
"option.series[0].data[4] = option.series[0].data[4] + %5;"
"option.graphic.elements[0].style.text= '%6';"
"myChart.setOption(option, true);"
)
.arg(qrand()%100)
.arg(qrand()%100)
.arg(qrand()%100)
.arg(qrand()%100)
.arg(qrand()%100)
.arg(_dateTime.toString("yyyy-MM"));
runJsScript(jsStr);
}

清除数据

void BarAutoSortEChartWidget::on_pushButton_clear_clicked()
{
_dateTime.setSecsSinceEpoch(0);
QString jsStr = QString(
"option.series[0].data[0] = 0;"
"option.series[0].data[1] = 0;"
"option.series[0].data[2] = 0;"
"option.series[0].data[3] = 0;"
"option.series[0].data[4] = 0;"
"option.graphic.elements[0].style.text= '%1';"
"myChart.setOption(option, true);"
)
.arg(_dateTime.toString("yyyy-MM"));
runJsScript(jsStr);
}
 

Demo源码

BarAutoSortEChartWidget.h

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

BarAutoSortEChartWidget.cpp

#include "BarAutoSortEChartWidget.h"
#include "ui_BarAutoSortEChartWidget.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") BarAutoSortEChartWidget::BarAutoSortEChartWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::BarAutoSortEChartWidget),
_pWebEngineView(0),
_pWebEnginePage(0),
_pWebChannel(0),
_htmlDir("D:/qtProject/echartsDemo/echartsDemo/modules/barAutoSortEChartWidget/html"), // 使用了绝对路径,引到html文件夹
_indexFileName("eChartWidget.html"),
_timerId(-1)
{
ui->setupUi(this); QString version = "v1.0.0";
setWindowTitle(QString("基于Qt的ECharts条状图(自动排序)Demo %1(长沙红胖子).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);
#endif initControl();
} BarAutoSortEChartWidget::~BarAutoSortEChartWidget()
{
delete ui;
} void BarAutoSortEChartWidget::initControl()
{
_pWebEngineView = new QWebEngineView(this);
_pWebEnginePage = new QWebEnginePage(this);
_pWebChannel = new QWebChannel(this);
QString filePath;
#if 1
filePath = QString("%1/%2").arg(_htmlDir).arg(_indexFileName);
#else
filePath = "qrc:/barAutoSortEChartWidget/html/eChartWidget.html";
#endif
LOG << "file exist:" << QFile::exists(filePath) << filePath;
#if 0
// 打印html文件内容
QFile file(_indexFilePath);
file.open(QIODevice::ReadOnly);
LOG << QString(file.readAll());
file.close();
#endif
connect(_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 BarAutoSortEChartWidget::slot_loadFinished(bool result)
{
if(result)
{
initJs();
// 因为使用布局,在没有完全构造之前,其大小是不可预期的,等构造完成后,布局的大小才会形成,此时再初始化一次
resizeEvent(0);
}
} void BarAutoSortEChartWidget::initJs()
{
_initJsStr = QSTRING(
"option = {"
" xAxis: {"
" max: 'dataMax'"
" },"
" yAxis: {"
" type: 'category',"
" data: ['特斯拉', '奔驰', '宝马', '理想', '蔚来'],"
" inverse: true,"
" animationDuration: 300,"
" animationDurationUpdate: 300,"
" max: 4"
" },"
" series: ["
" {"
" realtimeSort: true,"
" name: 'X',"
" type: 'bar',"
" data: [10,20,50,10,30],"
" label: {"
" show: true,"
" position: 'right',"
" valueAnimation: true"
" },"
" itemStyle: {"
" color: function(params) {"
" var colorList = ['#EE14FF', '#F092FF', '#FF61FE', '#A02F99', '#F00682']; /* 注意1:需要分号 */"
" return colorList[params.dataIndex]; /* 注意2:需要dataIndex,获取序号 */"
" }"
" }"
" },"
" ],"
" graphic: {"
" elements: [ /* 时间标志 */"
" {"
" type: 'text', "
" right: 160,"
" bottom: 100,"
" style: {"
" text: '1970-01',"
" font: 'bolder 100px monospace',"
" fill: 'rgba(100, 100, 100, 0.25)'"
" },"
" z: 100"
" }"
" ]"
" },"
" legend: {"
" show: false,"
" },"
" animationDuration: 0,"
" animationDurationUpdate: 1000,"
" animationEasing: 'linear',"
" animationEasingUpdate: 'linear'"
"};"
"myChart.setOption(option);");
runJsScript(_initJsStr);
} void BarAutoSortEChartWidget::runJsScript(QString str)
{
if(_pWebEnginePage)
{
_pWebEnginePage->runJavaScript(str);
}
} void BarAutoSortEChartWidget::resizeEvent(QResizeEvent *event)
{
if(_pWebEngineView)
{
_pWebEngineView->setGeometry(ui->label_echarts->geometry());
LOG << ui->label_echarts->geometry();
}
} void BarAutoSortEChartWidget::timerEvent(QTimerEvent *event)
{
_dateTime = _dateTime.addMonths(1);
if(_dateTime >= QDateTime::currentDateTime())
{
if(_timerId != -1)
{
killTimer(_timerId);
_timerId = -1;
}
}
QString jsStr = QString(
"option.series[0].data[0] = option.series[0].data[0] + %1;"
"option.series[0].data[1] = option.series[0].data[1] + %2;"
"option.series[0].data[2] = option.series[0].data[2] + %3;"
"option.series[0].data[3] = option.series[0].data[3] + %4;"
"option.series[0].data[4] = option.series[0].data[4] + %5;"
"option.graphic.elements[0].style.text= '%6';"
"myChart.setOption(option, true);"
)
.arg(qrand()%100)
.arg(qrand()%100)
.arg(qrand()%100)
.arg(qrand()%100)
.arg(qrand()%100)
.arg(_dateTime.toString("yyyy-MM"));
runJsScript(jsStr);
} void BarAutoSortEChartWidget::on_pushButton_clear_clicked()
{
_dateTime.setSecsSinceEpoch(0);
QString jsStr = QString(
"option.series[0].data[0] = 0;"
"option.series[0].data[1] = 0;"
"option.series[0].data[2] = 0;"
"option.series[0].data[3] = 0;"
"option.series[0].data[4] = 0;"
"option.graphic.elements[0].style.text= '%1';"
"myChart.setOption(option, true);"
)
.arg(_dateTime.toString("yyyy-MM"));
runJsScript(jsStr);
} void BarAutoSortEChartWidget::on_pushButton_flush_clicked()
{
QString jsStr =
"var empty = {};"
"myChart.setOption(empty, true);"
"myChart.setOption(option, true);";
runJsScript(jsStr);
} void BarAutoSortEChartWidget::on_pushButton_start_clicked()
{
if(_timerId == -1)
{
LOG << ui->lineEdit_interval->text().toInt();
_timerId = startTimer(ui->lineEdit_interval->text().toInt());
_dateTime.setSecsSinceEpoch(0);
QString jsStr = QString(
"option.series[0].data[0] = 0;"
"option.series[0].data[1] = 0;"
"option.series[0].data[2] = 0;"
"option.series[0].data[3] = 0;"
"option.series[0].data[4] = 0;"
"option.graphic.elements[0].style.text= '%1';"
"myChart.setOption(option, true);"
)
.arg(_dateTime.toString("yyyy-MM"));
runJsScript(jsStr); ui->pushButton_start->setText("停止统计");
}else{
if(_timerId != -1)
{
killTimer(_timerId);
_timerId = -1;
}
ui->pushButton_start->setText("开始统计");
}
} void BarAutoSortEChartWidget::on_pushButton_reset_clicked()
{
initJs();
}
 

工程模板v1.4.0

  

 

入坑

入坑一:排序图问题无法自动排序

问题

  没有排序:
  

原理

  这里之前我们已经遇见各种坑了,所以直接上调试工具,将Qt的js初始化代码在调试工具当中跑,如下图,web调试网页效果:
  

解决方法

  自己调整序号,交换数据可以实现,但是无法实现上下条交换的动画了。

Qt+ECharts开发笔记(五):ECharts的动态排序柱状图介绍、基础使用和Qt封装Demo的更多相关文章

  1. echarts使用笔记五:echarts的Zoom控件

    option = { title: { text: '趋势' }, tooltip : { trigger: 'axis', show:true, axisPointer : { // 坐标轴指示器, ...

  2. Django开发笔记五

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.页面继承 定义base.html: <!DOC ...

  3. libzip开发笔记(二):libzip库介绍、ubuntu平台编译和工程模板

    前言   Qt使用一些压缩解压功能,选择libzip库,libzip库比较原始,也是很多其他库的基础支撑库,编译过了windows版本,有需求编译一个ubuntu版本的,交叉编译需求的同样可参照本文章 ...

  4. zlib开发笔记(四):zlib库介绍、编译windows vs2015x64版本和工程模板

    前言   Qt使用一些压缩解压功能,介绍过libzip库编译,本篇说明zlib库.需要用到zlib的msvc2015x64版本,编译一下.   版本编译引导 zlib在windows上的mingw32 ...

  5. zlib开发笔记(三):zlib库介绍、在ubuntu上进行arm平台交叉编译

    前言   方便做嵌入式arm的交叉移植zlib库.   Zlib库   zlib被设计为一个免费的,通用的,法律上不受限制的-即不受任何专利保护的无损数据压缩库,几乎可以在任何计算机硬件和操作系统上使 ...

  6. Qt+ECharts开发笔记(二):Qt窗口动态调整大小,使ECharts跟随Qt窗口大小变换而变换大小

    前言   上一篇将ECharts嵌入Qt中,在开始ECharts使用之前,还有一个很重要的功能,就是在窗口变换大小的时候,ECharts的图表尺寸也要跟随Qt窗口变换大小而变换大小.   Demo演示 ...

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

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

  8. Qt+ECharts开发笔记(四):ECharts的饼图介绍、基础使用和Qt封装百分比图Demo

    前言   前一篇介绍了横向柱图图.本篇将介绍基础饼图使用,并将其封装一层Qt.  本篇的demo使用隐藏js代码的方式,实现了一个饼图的基本交互方式,并预留了Qt模块对外的基础接口.   Demo演示 ...

  9. 安卓开发笔记——关于开源项目SlidingMenu的使用介绍(仿QQ5.0侧滑菜单)

    记得去年年末的时候写过这个侧滑效果,当时是利用自定义HorizontalScrollView来实现的,效果如下: 有兴趣的朋友可以看看这篇文件<安卓开发笔记——自定义HorizontalScro ...

随机推荐

  1. VirtualBox 相关命令行

    简介 由于之前项目有一个需求,则是自动化创建虚拟机并加载相关配置,创建虚拟机无法避免对于虚拟机系统的设置,因此采用导入虚拟机的方式,并通过查阅virtualbox相关手册,知晓virtualbox可以 ...

  2. Odoo14 设置Binary字段默认值

    1 # Odoo 中的附件也就是Binary字段都是经过特殊处理的 2 # 首先是上传的时候会进行base64编码后再上传到服务器 3 # 服务器进行压缩存放在odoo文件仓库中 4 # 每个odoo ...

  3. 小白之Python基础(二)

    一.字符串 1.字符串编码发展: 1)ASCII码: 一个字节去表示 (8个比特(bit)作为一个字节(byte),因此,一个字节能表示的最大的整数就是255(二进制11111111 = 十进制255 ...

  4. 出票系统:根据淡旺季的月份和年龄,打印票价[课后练习] 出票系统:根据淡旺季的月份和年龄,打印票价[课后练习] 4 10旺季: 4 10旺季: 成人(18-60) : 60 成人(18-60):60 儿童(<18) :半价 儿童(<18):半价 老人(>60) :1/3 老人(>60):1/3 淡季: 淡季: 成人: 40 成人:40 其他: 20 其他:20

    用if适合新手练习 package LianXiTi;import java.util.Scanner;public class first2 {// 出票系统:根据淡旺季的月份和年龄,打印票价[课后 ...

  5. React报错之react component changing uncontrolled input

    正文从这开始~ 总览 当input的值被初始化为undefined,但后来又变更为一个不同的值时,会产生"A component is changing an uncontrolled in ...

  6. 原生js也可以自定义组件

    Web Components 是一套不同的技术,允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的web应用中使用它们. 它由三项主要技术组成,它们可以一起使用来创建封装功能的定制元 ...

  7. 【JDBC】学习路径4-分页查询

    第一章:什么是分页查询呢? 简而言之,分页数 就是百度搜索引擎中的网页的页数. 分页查询,就是从数据库中提取一部分出来,给用户. 用处:减少服务器负担. 为了方便测试,我们先给数据库添加大量信息. 还 ...

  8. 【JAVA】学习路径64-补充-编写一个会抛异常的方法

    有一些方法,在调用的时候有可能会出错,所以我们使用这些方法的时候会使用try catch. 比如InputStream里面的read()方法等等,那么这些方法是怎么实现抛异常的效果的呢? 能抛异常的方 ...

  9. KingbaseES TOAST存储方式

    KingbaseES为"大字段"的物理存储提供了TOAST功能,通过合适的配置策略能够减少IO次数和扫描块数,进而提升查询速度. TOAST:The Oversized-Attri ...

  10. 【面试题】JS第七种数据类型Symbol详解

    JS第七种数据类型Symbol详解 点击打开视频讲解更加详细 一.什么是Symbol? Symbol是ES6中引入的一种新的基本数据类型,用于表示一个独一无二的值.它是JavaScript中的第 七种 ...