赞
踩
数据的展示自然离不开图表,qt默认安装没有将QtCharts模块集成并社区版中,导致只能自己编译或使用第三方图库,如chartDirector或qwtplot等等。
本次介绍Qt在qml中使用QtCharts绘制稍复杂的饼图示例,并且该饼图提供一个接口传入数据并非一个简单的demo程序。
首先在安装Qt时要选中QtCharts模块,这点就不介绍了。
先来看一下效果
中间为第一环绘制了第一层的数据比例,第二层是以第一层为基础,将第一层的继续分比例显示。这里我们先来熟悉一下画饼图的控件
- PieSeries{
- startAngle: 起始角度
- endAngle: 终止角度
- holeSize: 内狐离圆心的距离
- size: 外狐离圆心的距离
- }
以上只列举了本次博客用到的主要属性,如果还想了解其它属性请查看Qt帮助文档。下一个控件是PieSlice
- PieSlice{
- angleSpan: 狐所占角度
- labelVisible: 是否显示标签
- label: 标签显示内容
- value: 狐所代表的值
- }
知道以上两个控件后,我们大概可以知道,饼图是由扇形组成的,而要想出现环状效果,只要使扇形内儿离圆心的距离大于0,且外儿离圆心的距离
- ChartView{
- id: chartView
- title: "2017-05-12 至 2017-08-29电信诈骗统计饼图"
- anchors.fill: parent
- legend.alignment: Qt.AlignRight
- antialiasing: true
- animationOptions: ChartView.AllAnimations
- property real sumAngle: 0
-
- PieSeries{
- PieSlice{
- id: sliceBank
- labelVisible: true
- labelPosition: PieSlice.LabelInsideHorizontal
- label: qsTr("网银止付 ") + (new Array(2).join('0') + percentage * 100).slice(-2) + "%"
- value: pieBankSeries.sum
- }
-
- PieSlice{
- id: sliceCall
- labelVisible: true
- labelPosition: PieSlice.LabelInsideHorizontal
- label: qsTr("智能追呼 ") + (new Array(2).join('0') + percentage * 100).slice(-2) + "%"
- value: pieCallSeries.sum
- }
- }
-
- PieSeries{
- id: pieBankSeries
- size: 0.8
- holeSize: 0.7
- startAngle: 0
- endAngle: sliceBank.angleSpan
- PieSlice{
- labelVisible: true
- label: qsTr("中国银行")
- value: 120
- }
- PieSlice{
- labelVisible: true
- label: qsTr("工商银行")
- value: 130
- }
- PieSlice{
- labelVisible: true
- label: qsTr("招商银行")
- value: 142
- }
- }
-
- PieSeries{
- id: pieCallSeries
- size: 0.8
- holeSize: 0.7
- startAngle: sliceBank.angleSpan
- endAngle: 360
-
- PieSlice{
- labelVisible: true
- label: qsTr("中国电信")
- value: 123
- }
- PieSlice{
- labelVisible: true
- label: qsTr("中国联通")
- value: 98
- }
- PieSlice{
- labelVisible: true
- label: qsTr("中国移动")
- value: 400
- }
- }
- }
像上面这样我们便可以画出上图一样的饼图,但是这样很明显,饼图的数据很死,能表示的数据也有限。所以我们应该把它做成接口。
- [{model: "网银止付",data: [{label: "招商银行",total_count: 115},
- {label: "工商银行",total_count: 200},
- {label: "中国银行",total_count: 220}]},
- {model: "智能追呼",data: [{label: "中国移动",total_count: 100},
- {label: "中国联通",total_count: 89},
- {label: "中国电信",total_count: 400}]}]
解析数据的方法因人而异,这里我分成了两步,一是写了一个画饼图的方法,二是写了一个解析json并调用画饼图的方法的方法。
- function createPieSeries(pieArgObj){
- var str = "import QtQuick 2.7;import QtCharts 2.0;PieSeries{}";
- var pieSeriesObj = Qt.createQmlObject(str,chartView,"dynamicSnippet1"); //创建一个PieSeries以chartView为父对象
- pieSeriesObj.startAngle = pieArgObj.startAngle; //起始角度
- pieSeriesObj.endAngle = pieArgObj.endAngle; //终止角度
- var dataArray = pieArgObj.data;
- var dataCount = dataArray.length;
-
- for(var i=0;i<dataCount;i++){
- var sliceObj = pieSeriesObj.append(dataArray[i].label,dataArray[i].total_count); //通过PieSeries的append方法添加PieSlice
- sliceObj.labelVisible = true; //设置PieSlice的标签可见
- sliceObj.label = dataArray[i].label; //设置PieSlice的标签内容
- }
-
- if(pieArgObj.position == 0){ //0代表是内环,此时显示百分比
- var sliceCount = pieSeriesObj.count;
- for(var j =0; j<sliceCount;j++){
- sliceObj = pieSeriesObj.at(j);
- sliceObj.labelPosition = PieSlice.LabelInsideHorizontal //设置PieSlice的label显示位置
- sliceObj.label = sliceObj.label + " " + (new Array(2).join('0') + sliceObj.percentage * 100).slice(-2) + "%"; //保留两位小数,并以百
- } //分比显示
- }
-
- return pieSeriesObj;
- }
解析数据的方法如下
- function loadData(jsObj){
- if(!(jsObj instanceof Array)){ //如果不是array,直接返回
- console.log("errror argument!")
- return;
- }
-
- var dataLength = jsObj.length;
- var modelArray = new Array();
- var modelObject = new Object();
- for(var i=0;i<dataLength;i++){ //获取网银止付和智能追呼的总值,通过计算子块的和;
- var nodeData = jsObj[i];
- var nodeDataArray = nodeData.data;
- var nodeDataArrayLength = nodeDataArray.length;
- var pieSeriesSumValue = 0
- for(var j=0;j<nodeDataArrayLength;j++){
- pieSeriesSumValue += nodeDataArray[j].total_count;
- }
- modelArray[i] = {label: nodeData.model,total_count: pieSeriesSumValue};
- }
-
- var obj = createPieSeries({startAngle:0,endAngle:360,data: modelArray,position: 0}); //先创建最里环
-
- var endAngle = new Number();
- for(var j=0;j<dataLength;j++){
- var curAngle = obj.at(j).angleSpan; //
- endAngle += curAngle;
- var subObj = createPieSeries({startAngle: endAngle - curAngle,endAngle: endAngle,data: jsObj[j].data,position: 1}); //statAngle为最里环
- subObj.holeSize = 0.7; //的每个PieSlice的angleSpan之各减去第二环当前的角度,endAngle为最里环每个PieSlice的angleSpan和
- subObj.size = 0.8; //设置内狐和外狐离圆心的距离。
- }
- }
- import QtQuick 2.8
- import QtCharts 2.0
- import QtQuick.Window 2.2
-
- Window {
- visible: true
- width: 640
- height: 480
- title: qsTr("Hello World")
-
- Item {
- anchors.fill: parent
- ChartView{
- id: chartView
- title: "2017-05-12 至 2017-08-29电信诈骗统计饼图"
- anchors.fill: parent
- legend.alignment: Qt.AlignRight
- antialiasing: true
- animationOptions: ChartView.AllAnimations
- property real sumAngle: 0
-
- }
-
- function createPieSeries(pieArgObj){
- var str = "import QtQuick 2.7;import QtCharts 2.0;PieSeries{}";
- var pieSeriesObj = Qt.createQmlObject(str,chartView,"dynamicSnippet1");
- pieSeriesObj.startAngle = pieArgObj.startAngle;
- pieSeriesObj.endAngle = pieArgObj.endAngle;
- var dataArray = pieArgObj.data;
- var dataCount = dataArray.length;
-
- for(var i=0;i<dataCount;i++){
- var sliceObj = pieSeriesObj.append(dataArray[i].label,dataArray[i].total_count);
- sliceObj.labelVisible = true;
- sliceObj.label = dataArray[i].label;
- }
-
- if(pieArgObj.position == 0){
- var sliceCount = pieSeriesObj.count;
- for(var j =0; j<sliceCount;j++){
- sliceObj = pieSeriesObj.at(j);
- sliceObj.labelPosition = PieSlice.LabelInsideHorizontal
- sliceObj.label = sliceObj.label + " " + (new Array(2).join('0') + sliceObj.percentage * 100).slice(-2) + "%";
- }
- }
-
- return pieSeriesObj;
- }
-
- function loadData(jsObj){
- if(!(jsObj instanceof Array)){
- console.log("errror argument!")
- return;
- }
-
- var dataLength = jsObj.length;
- var modelArray = new Array();
- var modelObject = new Object();
- for(var i=0;i<dataLength;i++){
- var nodeData = jsObj[i];
- var nodeDataArray = nodeData.data;
- var nodeDataArrayLength = nodeDataArray.length;
- var pieSeriesSumValue = 0
- for(var j=0;j<nodeDataArrayLength;j++){
- pieSeriesSumValue += nodeDataArray[j].total_count;
- }
- modelArray[i] = {label: nodeData.model,total_count: pieSeriesSumValue};
- }
-
- var obj = createPieSeries({startAngle:0,endAngle:360,data: modelArray,position: 0});
-
- var endAngle = new Number();
- for(var j=0;j<dataLength;j++){
- var curAngle = obj.at(j).angleSpan;
- endAngle += curAngle;
- var subObj = createPieSeries({startAngle: endAngle - curAngle,endAngle: endAngle,data: jsObj[j].data,position: 1});
- subObj.holeSize = 0.7;
- subObj.size = 0.8;
- }
- }
-
- Component.onCompleted: loadData([{model: "网银止付",data: [{label: "招商银行",total_count: 115},
- {label: "工商银行",total_count: 200},
- {label: "中国银行",total_count: 220}]},
- {model: "智能追呼",data: [{label: "中国移动",total_count: 100},
- {label: "中国联通",total_count: 89},
- {label: "中国电信",total_count: 400}]}])
- }
- }
这个结果就是最顶上的饼图,我修改数据如下之后
- Component.onCompleted: loadData([{model: "网银止付",data: [{label: "招商银行",total_count: 115},
- {label: "工商银行",total_count: 200},
- {label: "中国银行",total_count: 220}]},
- {model: "智能追呼",data: [{label: "中国移动",total_count: 100},
- {label: "中国联通",total_count: 89},
- {label: "中国电信",total_count: 400}]},
- {model: "其它",data: [{label: "报纸",total_count: 100},
- {label: "杂志",total_count: 89},
- {label: "书刊",total_count: 98}]}])
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。