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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt+ECharts开发笔记:ECharts的动态排序柱状图介绍基础使用和Qt封装Demo相关的知识,希望对你有一定的参考价值。

前言

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

<br>

Demo演示

  

<br>

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
;

  

<br>

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);

<br>

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();

<br>

工程模板v1.4.0

  

<br>

入坑

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

问题

  没有排序:   

原理

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

解决方法

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

以上是关于Qt+ECharts开发笔记:ECharts的动态排序柱状图介绍基础使用和Qt封装Demo的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

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

Qt+ECharts开发笔记:ECharts介绍下载和Qt调用ECharts基础柱状图Demo

Qt+ECharts开发笔记:ECharts介绍下载和Qt调用ECharts基础柱状图Demo