欢迎光临散文网 会员登陆 & 注册

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

2022-10-05 12:58 作者:红胖子_AAA红模仿  | 我要投稿

前言

  上一篇的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_OBJECTpublic:    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的评论 (共 条)

分享到微博请遵守国家法律