在QT中集成Echarts

Echarts是百度的可視化圖表庫(js),有各類漂亮的折線、餅、柱、雷達、散點圖,以前作網頁信息圖表時就體會到它具備很強大的表達能力(不單單是展現數據,更重要的是表達信息),因此很想把它集成到QT中,代替目前手頭已開發的軟件中的qwt。
目標:
在QT實現的軟件中嵌入Echarts折線圖,折線圖中的數據、標題等從qt部分傳給Echarts的js部分。javascript

實現:
1.在QT界面中使用QWebView來裝載一個包含Echarts折線圖的html頁面。
2.QT向html傳遞數據時使用json格式字符串。
3.html和js文件做爲QT RESOURCES打包編譯,這樣發佈時只有一個可執行程序,沒有額外的配置。html

效果圖

遺留問題:多是操做系統的X11庫有bug,我遭遇了下面這樣的錯誤,有時在關閉界面時會coredump。java

XIO:  fatal IO error 11 (資源暫時不可用) on X server "愼U"
      after 36191 requests (36190 known processed) with 0 events remaining.

使用到的開源軟件以下,很是感謝前人的輪子!!!
Echarts實例
qt與echarts配合打造最強圖表庫 個人代碼是在他的開源上的一些增長
cJSON 一個很是好用的C語言解析JSON的開源庫jquery

個人代碼文件結構以下所示,res目錄下是html和js文件,經過qrc文件指定資源,就能夠將其靜態打包到可執行程序中,cJSON是處理json結構對象和字符串的c庫,widget是處理加載頁面,傳參到js的qt程序
文件列表
部分源碼在這裏,寫了一些註釋。
main.cppweb

#include "widget.h"
#include <QApplication>
#include <QTextCodec>

int main(int argc, char *argv[])
{
    QTextCodec::setCodecForTr( QTextCodec::codecForName("utf8") );
    QTextCodec::setCodecForCStrings( QTextCodec::codecForName("utf8") );
    QTextCodec::setCodecForLocale( QTextCodec::codecForName("utf8") );
    Q_INIT_RESOURCE(main);
    QApplication a(argc, argv);

    Widget w;
    w.show();
    return a.exec();
}

widget.cppjson

#include <sys/time.h>
#include "widget.h"
#include "ui_widget.h"
#include "cJSON.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->webView->load(QUrl("qrc:/res/curve.html")); //加載頁面
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_btnLine_clicked()
{
    // 建立一些隨機數
    float array[1440];
    int max=1000, min=0;
    struct    timeval tv_rand;
    for (int i=0; i<1440; i++)
    {
        gettimeofday(&tv_rand, (struct timezone*)0);
        srand(tv_rand.tv_usec);
        array[i] = (rand() % ((int)max*10000 - (int)min*10000))/10000.0 + min;
    }
    
    // 構建用於傳輸數據的json對象
    cJSON *root;
    char *out;
    root=cJSON_CreateObject();    
    // json對象結構 {"title":"xxxxx", "value":[float array]}
    cJSON_AddStringToObject(root, "title", "日負荷曲線"); // 有中文的需求要注意使用UTF-8編碼
    cJSON_AddItemToObject(root, "value", cJSON_CreateFloatArray(array, 1440));
    out=cJSON_Print(root); // json對象轉字符串
    cJSON_Minify(out); // 去掉字符串中的換行和縮進
    QString str = QString(out);
    cJSON_Delete(root);
    
    // 把json字符串中全部雙引號前面再加上一個轉義符 
    // 由於這個字符串到了js裏面還要被parseJSON一次,因此\\不可少
    str.replace(QRegExp("\""), "\\\""); 
    
    // callfromqt是js中的函數名 str是其入參
    QString strVal = QString("callfromqt(\"%1\");").arg(str);
    printf("strVal : %s \n", strVal.toStdString().c_str());
    
    // 調用js中的函數
    ui->webView->page()->mainFrame()->evaluateJavaScript(strVal);  
}

curve.htmlecharts

<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <title>ECharts</title>
</head>
<body>
    <!-- 爲ECharts準備一個具有大小(寬高)的Dom -->
    <div id="main" style="height:400px"></div>
    <!-- 由於連js都會被打包到可執行程序中,因此這裏引入echarts-all.js而不是require動態加載 -->
    <script src="jquery.min.js"></script>
    <script src="build/dist/echarts-all.js"></script>
    <script type="text/javascript">
    
    // 基於準備好的dom,初始化echarts圖表, macarons是echarts主題,換樣式的,可略
    var myChart = echarts.init(document.getElementById('main'),'macarons'); 
    // 組織option
   var option = {
        title : {
            text: '' //名字由qt傳進來
        },
        tooltip:{
            show : true,
            trigger: 'axis',  // 座標軸觸發 也能夠item數據點觸發
            formatter:function (params){ // tip的樣式
                var res = '時間 : ' + params[0].name +'<br/>';
                for (var i = 0, l = params.length; i < l; i++) {
                    res += '<br/>' + params[i].seriesName + ' : ' + params[i].value;
                }    
                return res;
            }
        },
        calculable : false,
        xAxis : [
            {
                type : 'category',
                boundaryGap : false,
                axisLabel:{interval:0},
                data : []
            }
        ],
        yAxis : [
            {
                type : 'value'
            }
        ],
        series : [
            {
                name:'今日',
                type:'line',
                data:[]
            }
        ]
    };   
    
    //窗體自適應    
    window.onresize = myChart.resize;       
    
    // 爲echarts對象加載數據 
    function callfromqt(str)
    {
        var obj = $.parseJSON(str); // 可能個人QT版本有點低,webkit不能支持原生的JSON.parse
        if (obj.value.length < 1)
                return;
        
        option.title.text=obj.title;       
        option.series[0].data =  obj.value;    
        // 下面是根據傳入的採樣點數拼座標軸 可略
        option.xAxis[0].data = getDayXAsis(obj.value.length);
        if ( option.xAxis[0].data.length > 12)
            option.xAxis[0].axisLabel.interval = option.xAxis[0].data.length/12 -1;
        else
            option.xAxis[0].axisLabel.interval = 0;
        
        // 畫折線圖    
        myChart.setOption(option); 
    }
             
    // 根據數據點數建立日曲線的x軸標籤
    function getDayXAsis(split_num)
    {
        var xasis = [];
        // 若是是288點就5分鐘一個標籤 96點就15分鐘一個標籤
        var offset = 86400/split_num;
        var d = new Date(1999, 1, 1);
        for (var i=0; i<split_num; i++)
        {
            var nd = new Date();
            nd.setTime(d.getTime() +offset*1000*i);    
            var str = compZero(nd.getHours(),2)+":"+compZero(nd.getMinutes(),2);
            xasis.push(str);
        }
        return xasis;
    }
            
    // 左補0
    function compZero(intn, bits)
    {
        var int_str = "" + intn;
        if (int_str.length >= bits)
                return int_str;
                
        var comp_str = "";
        var comp_len = bits - int_str.length;
        for (var i=0; i<comp_len; i++)
            comp_str += "0";
                
        comp_str += int_str;
            return comp_str;
    }
    
    </script>
</body>

小結:
QT向js傳遞參數中有中文的話,qt文件要存爲UTF-8的格式,不然會形成亂碼。
以json字符串傳遞參數是,要對引號再加一次轉義符,不然在js中沒法解析。
Echarts在網頁上展現數據的性能號稱20W數據秒級出圖,但在QT中出圖的動畫效果有明顯卡頓,但仍在可接受範圍內。dom

相關文章
相關標籤/搜索