标签:
曾经收到过一份礼物,一个雪花飘落的程序,觉得效果很炫,通过前几篇的学习,我们已经掌握了贴图的一些技巧了,那么现在就可以自己实现了(当然你必须先拥有qt信号与槽的基础知识),这里先看效果,然后再分析如何实现。
效果图:
这个程序实现很久了,也是当初学习qt的时候写的,因为工作的原因,当初的部分设想,并没有全部实现,现在分享,供大家一起学习。
当初的设想:
1、雪花随机飘落
2、地面的花草,可以支持自由的move操作
3、地面的植物可以积聚到雪花。
因为工作的原因,第3点并没有实现,有兴趣的可以自己实现,接下来讲解一下实现步奏。
实现方案:
1、SnowNode雪花节点类,定义雪花的形状、初始化状态、行为
2、WaitFallen待飘落的雪花类,用于定时向屏幕投入雪花
3、Snowfalling 正在飘落的雪花,定时扫描雪花是否到达地上,雪花到达地上时,发送信号
4、Snowpack 地上的积雪,定时将积雪回收
5、GroundLife 地面物体
Vegetable 植物
6、SnowFrame雪花画面,对雪花进行统一管理功能插件:
PngButton 图片按钮
WidgetMove 普通的按钮移动
Virtual3DMove 将按钮虚拟成三维效果,按钮移动时进行放大和缩小
变量收集:
雪花池数量: 200
向屏幕投送雪花间隔: 1000
每次投送雪花数量:0-5
雪花飘落全程时间:10秒
关键点实现:
1、主窗体设置
1: //让程序无边框
2: setWindowFlags( Qt::FramelessWindowHint );3: //让程序背景透明
4: setAttribute(Qt::WA_TranslucentBackground, true);
2、建立雪花池、飘落、回收的联动,形成一个循环系统
1: connect(&m_snowWait, SIGNAL(falling(SNOWLIST*)), &m_snowFalling, SLOT(AcceptSnow(SNOWLIST*)));2: connect(&m_snowFalling, SIGNAL(snowLander(SNOWLIST*)), &m_snowLander, SLOT(LanderSnow(SNOWLIST*)));3: connect(&m_snowLander, SIGNAL(snowRecycle(SNOWLIST*)), &m_snowWait, SLOT(SnowRecycle(SNOWLIST*)));
3、每一朵雪花我们可以用一个button来承载,并为每一朵雪花定义飘落的行为。
雪花节点头文件:
1: #include <QToolButton>2: #include <QPropertyAnimation>3: class QPixmap;
4: class QPaintEvent;
5: class QPoint;
6: class QSize;
7:8: class SnowNode : public QToolButton9: {10: public:
11: static const int MAXSWOW ;12: SnowNode(QWidget *parent = 0);13: QSize GetSnowSize();14: bool IsLander();
15: void InitSnow();
16: void FallingAnimation();
17:18: protected:
19: void paintEvent(QPaintEvent *event);
20: private:
21: QString GetImgFileName();22: private:
23: QPixmap m_pixmap;24: QPropertyAnimation *m_animation;25: QSize m_areaSize;26: };
雪花节点实现文件:
1: #include "pubbase.h"
2: #include "snownode.h"
3: #include <QSize>4: #include <QPoint>5: #include <QBitmap>6: #include <QPixmap>7: #include <QToolButton>8: #include <QApplication>9: #include <QDesktopWidget>10: #include <QGraphicsScene>11: #include <QGraphicsView>12: const int SnowNode::MAXSWOW = 19;13:14: SnowNode::SnowNode(QWidget *parent):15: QToolButton(parent),m_animation(new QPropertyAnimation(this, "geometry"))16: {17: //必须设置为无边框,否则可见区域和图片绘制区域将出现不重叠
18: setWindowFlags( Qt::FramelessWindowHint );19: resize(GetSnowSize());20: //对图片进行缩放
21: m_pixmap.load(GetImgFileName());22: m_pixmap = m_pixmap.scaled(this->size(),Qt::IgnoreAspectRatio);
23: setHidden(true);
24: m_areaSize.setWidth(QApplication::desktop()->width());25: m_areaSize.setHeight(QApplication::desktop()->height());26: }27:28: //初始化雪花
29: void SnowNode::InitSnow()
30: {31: this->move(qrand() % m_areaSize.width(), -32);
32: }33:34: //设置雪花动画
35: void SnowNode::FallingAnimation()
36: {37: int x = qrand()% m_areaSize.width();
38: //雪花飘落全程时间
39: m_animation->setDuration(8000);40: m_animation->setStartValue(QRect( pos(), size()));41: m_animation->setEndValue(QRect( QPoint(x,m_areaSize.height()), size()));42: m_animation->start();43: }44:45: //返回雪花是否已着陆
46: bool SnowNode::IsLander()
47: {48: if(this->pos().y() >= m_areaSize.height()49: && m_animation->state() == QAbstractAnimation::Stopped50: )51: {52: return true;53: }54: return false;55: }56:57: void SnowNode::paintEvent(QPaintEvent *event)
58: {59: //绘制背景图片
60: this->setIcon(QIcon(m_pixmap));
61: this->setIconSize(size());
62: //将png图片透明部分设置为穿透
63: this->setMask(m_pixmap.mask());
64: //绘制
65: QToolButton::paintEvent(event);66:67: }68:69: //每一朵雪花的大小,采用随机生成
70: QSize SnowNode::GetSnowSize()71: {72: int x = qrand() % 10;
73: return x >= 6 ? QSize(32,32) : x >= 3 ? QSize(24,24) : QSize(16,16);
74: }75:76: //获取雪花文件名
77: QString SnowNode::GetImgFileName()78: {79: return QString().sprintf(":/image/_%d.png", qrand()% MAXSWOW);80: }81:
4、替换一个桌面背景
1: 调用windows API函数来设置桌面背景2: ::SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, (void*)imgFileName, SPIF_UPDATEINIFILE)
5、定义一个定时器,定时投放雪花即可
有想学习的盆友,可以留下你的邮箱地址,我会将完整的源码发给你。
标签:
原文地址:http://www.cnblogs.com/lingluotianya/p/4430379.html