版权声明
该文章原创于Qter开源社区(www.qter.org),作者yafeilinux,转载请注明出处!
导语
当使用图表时我们大多关心数据本身,而对于实现形式,一般会使用标准的样式。但是在一些场合,我们更关心数据的展示效果而不是数字本身。对于下面两张图片效果,你更喜欢哪一个?
是标准化的坐标网格:
还是梦幻的科技元素:
如果只看静态图片还是没有感觉,那就看下动态效果吧!
很炫酷,不是吗?下面就跟随我来实现科幻的数据曲线吧!
环境:Windows 7 + Qt 5.12.0
正文
第一步 创建一个曲线图表
注意:在安装Qt时请务必选择Qt Charts模块,不然该模块将无法使用。
首先创建一个Qt Quick Application - Empty应用,完成后修改main.qml文件如下:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtCharts 2.3
Window {
visible: true
width: 800
height: 480
ChartView {
id: chartView
anchors.fill: parent
antialiasing: true
SplineSeries {
name: "SplineSeries"
XYPoint { x: 0; y: 0.0 }
XYPoint { x: 1.1; y: 3.2 }
XYPoint { x: 1.9; y: 2.4 }
XYPoint { x: 2.1; y: 2.1 }
XYPoint { x: 2.9; y: 2.6 }
XYPoint { x: 3.4; y: 2.3 }
XYPoint { x: 4.1; y: 3.1 }
}
}
}
但现在程序还无法运行,因为Qt Charts模块是基于Qt图形视图框架的,为了使用Qt Charts模块,还需要在main.cpp文件中将:
#include <QGuiApplication>
修改为:
#include <QtWidgets/QApplication>
然后将:
QGuiApplication app(argc, argv);
修改为:
QApplication app(argc, argv);
接下来到.pro文件中添加widgets模块调用,即:
这样就可以编译运行程序了,效果如下图所示。
第二步 动态添加数据
1.首先我们需要提供要显示的数据,这里使用外部的XML文件来提供数据,为了简便,直接使用了Qt示例程序中的数据来进行演示,文件名称为speed.xml,我们将该文件添加到资源文件中。数据内容格式如下:
<?xml version="1.0" encoding="UTF-8"?>
<results>
<row>
<speedTrap>0</speedTrap>
<driver>Fittipaldi</driver>
<speed>104.12</speed>
</row>
... ...
2.然后使用XmlListModel来解析数据,需要先添加导入语句:
import QtQuick.XmlListModel 2.0
然后添加如下代码:
XmlListModel {
id: speedsXml
source: "speed.xml"
query: "/results/row"
XmlRole { name: "speedTrap"; query: "speedTrap/string()" }
XmlRole { name: "driver"; query: "driver/string()" }
XmlRole { name: "speed"; query: "speed/string()" }
onStatusChanged: {
if (status == XmlListModel.Ready) {
timer.start();
}
}
}
3.解析完数据后我们通过定时器来动态加载数据,先在根对象中新建一个属性,用于计数:
property int currentIndex: -1
然后添加定时器的定义:
Timer {
id: timer
interval: 800
repeat: true
triggeredOnStart: true
running: false
onTriggered: {
currentIndex++;
if (currentIndex < speedsXml.count) {
var lineSeries = chartView.series(speedsXml.get(0).driver);
if (!lineSeries) {
lineSeries = chartView.createSeries(ChartView.SeriesTypeSpline,
speedsXml.get(0).driver);
chartView.axisY().min = 0;
chartView.axisY().max = 250;
chartView.axisY().tickCount = 6;
chartView.axisY().titleText = "speed (kph)";
chartView.axisX().titleText = "speed trap";
chartView.axisX().labelFormat = "%.0f";
lineSeries.color = "#87CEFA"
chartView.animationOptions = ChartView.SeriesAnimations
}
lineSeries.append(speedsXml.get(currentIndex).speedTrap,
speedsXml.get(currentIndex).speed);
if (speedsXml.get(currentIndex).speedTrap > 3) {
chartView.axisX().max =
Number(speedsXml.get(currentIndex).speedTrap)+1;
} else {
chartView.axisX().max = 5;
chartView.axisX().min = 0;
}
chartView.axisX().tickCount = chartView.axisX().max
- chartView.axisX().min + 1;
} else {
timer.stop();
chartView.animationOptions = ChartView.AllAnimations;
chartView.axisX().min = 0;
chartView.axisX().max = speedsXml.get(currentIndex - 1).speedTrap;
}
}
}
这里在定时器中,每隔0.8秒就添加一组数据,在第一次运行时还创建了SplineSeries曲线图,因为这次我们重点不是讲解图表的基础知识,所以就不再对代码进行过多讲解。
4.最后,我们需要将前面在ChartView对象中定义的SplineSeries代码删除或注释掉,下面可以运行程序,看下效果了。
第三步 使用图形特效
接下来我们使用Qt Graphicl Effects为图表添加图形效果,在这之前,需要先对图表进行一些必要的处理。
1.首先在ChartView对象中添加代码,将图表背景设置为透明,并让图例隐藏:
backgroundColor: "transparent"
legend.visible: false
然后到Timer对象中,在:if (!lineSeries) {}最后添加如下代码来隐藏XY轴:
chartView.axisX().visible = false
chartView.axisY().visible = false
现在运行程序,效果是这样的:
2.接下来先添加导入语句:
import QtGraphicalEffects 1.12
然后在根对象中添加如下代码:
Glow {
id:glow
anchors.fill: chartView
radius: 18
samples: 37
color: "#87CEFA"
source: chartView
}
RadialBlur {
anchors.fill: chartView
source: chartView
angle: 360
samples: 20
}
ZoomBlur {
anchors.fill: chartView
source: chartView
length: 24
samples: 20
}
这里对图表分别使用了发光、镜像模糊和缩放模糊三种特效,更改不同的参数,特效会有所不同,大家可以多尝试下。下面来看下运行效果,现在已经出现梦幻曲线了,其实白色背景也蛮漂亮的。
为了更加突出发光效果,我们将背景设置为黑色,在Window根对象的开始添加一行代码:
现在运行程序,效果好像更加明显了。
第四步 化腐朽为神奇
其实现在特效曲线已经实现了,但看上去有点单薄,为了进一步突出科技效果,我们为其添加一些装饰。
1.我们在ChartView对象中添加子对象:
Image {
id: img
source: "circle.png"
width: 100; height: 100
x: -10; y: 230
visible: true
Behavior on rotation {
NumberAnimation {
duration: 800
easing.type: Easing.InOutElastic;
easing.amplitude: 2.0;
easing.period: 1.5
}
}
}
Text {
id:txt
width: 200; height: 20
x: 350; y: 55
font.pointSize: 20
font.family: "Cambria"
color: "#F8F8FF"
}
这里添加了一个图片和一个文本,图片作为曲线发射器,文本用来显示曲线数据,为了让二者可以共享图表的图形效果,这里将他们作为图表的子对象。
3.下面添加代码来为文本提供数据,并且让图片旋转起来。在Timer对象的
lineSeries.append(speedsXml.get(currentIndex).speedTrap,
speedsXml.get(currentIndex).speed);
语句下面添加如下代码:
txt.text = speedsXml.get(currentIndex).speed;
img.rotation += 360
运行程序,效果是这样的。
最后我们再添加代码,来为图表添加一个边框,在根对象最后添加如下代码:
Image {
id: border
source: "border.png"
anchors.fill: parent
}
Glow {
anchors.fill: border
radius: 18
samples: 37
color: "#87CEFA"
source: border
}
这里为边框也使用了发光特效,进一步突出科技感。现在,整个图表美化的过程就完成了,大家可以尝试进行修改,做出其他炫酷效果。
结语
要做出一些特殊效果,其实关键在于两点,一是知识面,二是套路。没有知识面,啥都不知道,那就什么也别说了。当有了知识面之后,知道什么模块能起到什么作用,下面就是学习一些套路,这里所说的套路既是经验也是规律,比如,你知道PS出来的图片为什么好看吗?你知道饭店炒的菜为什么比家里味道浓吗?编程的道理是相通的。
源码下载:
或到github下载源码:https://github.com/yafeilinux/effctchart
关注微信公众号,获取最新教程文章!
|