yafeilinux 发表于 2019-1-7 18:11:54

当Qt Charts遇上Qt Graphical Effects,梦幻科技曲线!

版权声明
该文章原创于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模块调用,即:
QT += quick 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根对象的开始添加一行代码:

color: "black"

现在运行程序,效果好像更加明显了。



第四步 化腐朽为神奇
其实现在特效曲线已经实现了,但看上去有点单薄,为了进一步突出科技效果,我们为其添加一些装饰。
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


关注微信公众号,获取最新教程文章!




张飞Dear 发表于 2019-3-21 13:54:15

你好,亚飞老师, Qt5.4 版本可以使用Qt Charts模块吗   

yafeilinux 发表于 2019-3-21 18:40:15

张飞Dear 发表于 2019-3-21 13:54
你好,亚飞老师, Qt5.4 版本可以使用Qt Charts模块吗

开源版本从Qt 5.7开始有的。

keyiangel 发表于 2020-3-11 20:41:43

好评如潮,必须顶楼主哈

AkEcbz 发表于 2020-5-30 09:23:42

豆子不够哇(*@ο@*) 哇~(*@ο@*) 哇~

lxdlbs371 发表于 2021-6-16 19:21:24

赞叹,顶楼主~

kenan64286 发表于 2023-3-31 12:00:27

报错:QQmlApplicationEngine failed to load component
qrc:/main.qml:22 plugin cannot be loaded for module "QtQuick.XmlListModel": ????????D:\Qt\Qt5.12.9\5.12.9\mingw73_32\qml\QtQuick\XmlListModel\qmlxmllistmodelplugind.dll???洢????????????????
已经添加了:import QtQuick.XmlListModel 2.12和QT += quick widgets charts xmlpatterns
怎么解决呢?

yafeilinux 发表于 2023-4-1 21:23:35

kenan64286 发表于 2023-3-31 12:00
报错:QQmlApplicationEngine failed to load component
qrc:/main.qml:22 plugin cannot be loaded for mo ...

可以先写个简单的示例测试这个能用不
页: [1]
查看完整版本: 当Qt Charts遇上Qt Graphical Effects,梦幻科技曲线!