找回密码
 立即注册
收起左侧

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

7
回复
37992
查看
[复制链接]
累计签到:1564 天
连续签到:1 天
来源: 2019-1-7 18:11:54 显示全部楼层 |阅读模式
版权声明

该文章原创于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



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





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
参与人数 5人气 +14 收起 理由
yangjun1 + 2
魂之恋歌 + 2 必须支持!
qt_wtw + 7 必须支持!
yuzhe + 2 很详细!
redtramp + 1 必须支持!

查看全部评分总评分 : 人气 +14

回复

使用道具 举报

累计签到:319 天
连续签到:1 天
2019-3-21 13:54:15 显示全部楼层
你好,亚飞老师, Qt5.4 版本可以使用Qt Charts模块吗   

点评

开源版本从Qt 5.7开始有的。  详情 回复 发表于 2019-3-21 18:40
回复 支持 反对

使用道具 举报

累计签到:1564 天
连续签到:1 天
2019-3-21 18:40:15 显示全部楼层
张飞Dear 发表于 2019-3-21 13:54
你好,亚飞老师, Qt5.4 版本可以使用Qt Charts模块吗

开源版本从Qt 5.7开始有的。
回复 支持 反对

使用道具 举报

累计签到:198 天
连续签到:1 天
2020-3-11 20:41:43 显示全部楼层
好评如潮,必须顶楼主哈
回复 支持 反对

使用道具 举报

尚未签到

2020-5-30 09:23:42 显示全部楼层
豆子不够哇(*@ο@*) 哇~(*@ο@*) 哇~
回复 支持 反对

使用道具 举报

累计签到:17 天
连续签到:1 天
2021-6-16 19:21:24 显示全部楼层
赞叹,顶楼主~
回复 支持 反对

使用道具 举报

尚未签到

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
怎么解决呢?

点评

可以先写个简单的示例测试这个能用不  详情 回复 发表于 2023-4-1 21:23
回复 支持 反对

使用道具 举报

累计签到:1564 天
连续签到:1 天
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 ...

可以先写个简单的示例测试这个能用不
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了