来源于微信公众号: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模块调用,即:
QT += quick widgets
这样就可以编译运行程序了,效果如下图所示。
第二步 动态添加数据
首先我们需要提供要显示的数据,这里使用外部的XML文件来提供数据,为了简便,直接使用了Qt示例程序中的数据来进行演示,文件名称为speed.xml,我们将该文件添加到资源文件中。数据内容格式如下:
<?xml version="1.0" encoding="UTF-8"?> <results> <row> <speedTrap>0</speedTrap> <driver>Fittipaldi</driver> <speed>104.12</speed> </row> ... ...
然后使用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(); } } }
解析完数据后我们通过定时器来动态加载数据,先在根对象中新建一个属性,用于计数:
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曲线图,因为这次我们重点不是讲解图表的基础知识,所以就不再对代码进行过多讲解。
最后,我们需要将前面在ChartView对象中定义的SplineSeries代码删除或注释掉,下面可以运行程序,看下效果了。
第三步 使用图形特效
接下来我们使用Qt Graphicl Effects为图表添加图形效果,在这之前,需要先对图表进行一些必要的处理。
首先在ChartView对象中添加代码,将图表背景设置为透明,并让图例隐藏:
backgroundColor: "transparent" legend.visible: false
然后到Timer对象中,在:if (!lineSeries) {}最后添加如下代码来隐藏XY轴:
chartView.axisX().visible = false chartView.axisY().visible = false
现在运行程序,效果是这样的:
接下来先添加导入语句:
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根对象的开始添加一行代码:
color: "black"
现在运行程序,效果好像更加明显了。
第四步 化腐朽为神奇
其实现在特效曲线已经实现了,但看上去有点单薄,为了进一步突出科技效果,我们为其添加一些装饰。
我们在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" }
这里添加了一个图片和一个文本,图片作为曲线发射器,文本用来显示曲线数据,为了让二者可以共享图表的图形效果,这里将他们作为图表的子对象。
下面添加代码来为文本提供数据,并且让图片旋转起来。在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出来的图片为什么好看吗?你知道饭店炒的菜为什么比家里味道浓吗?编程的道理是相通的。
---------------------------------------------------------------------------------------------------------------------- 我们尊重原创,也注重分享,文章来源于微信公众号:yafeilinux和他的朋友们,建议关注公众号查看原文。如若侵权请联系qter@qter.org。 ----------------------------------------------------------------------------------------------------------------------
|