这个数字时钟的源码可以在Qt Demo中找到,风格是仿Android的,不过该Demo中含有三种动画效果(鉴于本人未曾用过Android的系统,因此不知道Android的数字时钟是否也含有这三种效果),其分别为滑动、翻页和旋转。

由于本人的Qt Creator输入中文后显示的都是乱码,因而在此只能使用英文进行注释,后期如果有时间再进行中文的相关整理。可能有些地方理解并不是很正确。希望大家多多指正!

以下为源码:

  1. #include <QtCore>
  2. #include <QtGui>
  3. class Digits: public QWidget
  4. {
  5. Q_OBJECT
  6. public:
  7. /*Define three transition modes of the digital clock*/
  8. enum {
  9. Slide,
  10. Flip,
  11. Rotate
  12. };
  13. Digits(QWidget *parent)
  14. : QWidget(parent)
  15. , m_number(0)
  16. , m_transition(Slide)
  17. {
  18. setAttribute(Qt::WA_OpaquePaintEvent, true);
  19. //Widget paints all its pixels when it receives a paint event
  20. setAttribute(Qt::WA_NoSystemBackground, true);
  21. //Indicates that the widget has no background, i.e. when the widget receives paint events, the background is not automatically repainted.
  22. connect(&m_animator, SIGNAL(frameChanged(int)), SLOT(update()));
  23. //start animation
  24. m_animator.setFrameRange(0, 100);
  25. m_animator.setDuration(600);
  26. //Construct a 0.6-second timeline with a frame range of 0 - 100
  27. m_animator.setCurveShape(QTimeLine::EaseInOutCurve);
  28. //starts growing slowly, then runs steadily, then grows slowly again
  29. }
  30. /*Set transition when time changed*/
  31. void setTransition(int tr) {
  32. m_transition = tr;
  33. }
  34. /*Get transition mode*/
  35. int transition() const {
  36. return m_transition;
  37. }
  38. /*Set hours and minutes*/
  39. void setNumber(int n) {
  40. if (m_number != n) {
  41. m_number = qBound(0, n, 99);
  42. preparePixmap();
  43. update();
  44. }
  45. }
  46. /*Flip to next state*/
  47. void flipTo(int n) {
  48. if (m_number != n) {
  49. m_number = qBound(0, n, 99);
  50. m_lastPixmap = m_pixmap;
  51. preparePixmap();
  52. m_animator.stop();
  53. m_animator.start();
  54. }
  55. }
  56. protected:
  57. /*Draw the main frame of the digits area*/
  58. void drawFrame(QPainter *p, const QRect &rect) {
  59. p->setPen(Qt::NoPen);
  60. QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
  61. //Set linear gradient area
  62. gradient.setColorAt(0.00, QColor(245, 245, 245));
  63. gradient.setColorAt(0.49, QColor(192, 192, 192));
  64. gradient.setColorAt(0.51, QColor(245, 245, 245));
  65. gradient.setColorAt(1.00, QColor(192, 192, 192));
  66. //Creates stop points at the given position with the given color
  67. p->setBrush(gradient);
  68. QRect r = rect;
  69. p->drawRoundedRect(r, 15, 15, Qt::RelativeSize);
  70. /*
  71. Draws outer rectangle rect with rounded corners.
  72. Qt::RelativeSize specifies the size relative to the bounding rectangle,
  73. typically using percentage measurements.
  74. */
  75. r.adjust(1, 4, -1, -4);
  76. //Adds 1, 4, -1 and -4 respectively to the existing coordinates of the rectangle
  77. p->setPen(QColor(181, 181, 181));
  78. p->setBrush(Qt::NoBrush);
  79. p->drawRoundedRect(r, 15, 15, Qt::RelativeSize);
  80. //Draws inner rectangle rect with rounded corners.
  81. p->setPen(QColor(159, 159, 159));
  82. int y = rect.top() + rect.height() / 2 - 1;
  83. p->drawLine(rect.left(), y, rect.right(), y);
  84. //Draws the mid-line from (rect.left(), y) to (rect.right(), y) and sets the current pen position to (rect.right(), y)
  85. }
  86. /*Draw the digits*/
  87. QPixmap drawDigits(int n, const QRect &rect) {
  88. int scaleFactor = 2;
  89. #if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM)
  90. if (rect.height() > 240)
  91. scaleFactor = 1;
  92. #endif
  93. QString str = QString::number(n);
  94. if (str.length() == 1)
  95. str.prepend("0");
  96. //Ensure it is double-digit
  97. QFont font;
  98. font.setFamily("Helvetica");
  99. int fontHeight = scaleFactor * 0.55 * rect.height();
  100. font.setPixelSize(fontHeight);
  101. //Sets the font size to pixelSize pixels
  102. font.setBold(true);
  103. QPixmap pixmap(rect.size() * scaleFactor);
  104. pixmap.fill(Qt::transparent);
  105. QLinearGradient gradient(QPoint(0, 0), QPoint(0, pixmap.height()));
  106. //Constructs a linear gradient with interpolation area between (0,0) and (0,pixmap.height())
  107. gradient.setColorAt(0.00, QColor(128, 128, 128));
  108. gradient.setColorAt(0.49, QColor(64, 64, 64));
  109. gradient.setColorAt(0.51, QColor(128, 128, 128));
  110. gradient.setColorAt(1.00, QColor(16, 16, 16));
  111. //Creates stop points at the given position with the given color
  112. QPainter p;
  113. p.begin(&pixmap);
  114. p.setFont(font);
  115. QPen pen;
  116. pen.setBrush(QBrush(gradient));
  117. //Set penbrush with linergrident
  118. p.setPen(pen);
  119. p.drawText(pixmap.rect(), Qt::AlignCenter, str);
  120. //Draws the digit number(str here) within the provided rectangle
  121. p.end();
  122. return pixmap.scaledToWidth(width(), Qt::SmoothTransformation);
  123. //Returns a scaled copy of the image which is transformed using bilinear filtering
  124. }
  125. /*prepare the pixmap  */
  126. void preparePixmap() {
  127. m_pixmap = QPixmap(size());
  128. m_pixmap.fill(Qt::transparent);
  129. //Fills the pixmap with the given transparent black value (i.e., QColor(0, 0, 0, 0))
  130. QPainter p;
  131. p.begin(&m_pixmap);
  132. p.drawPixmap(0, 0, drawDigits(m_number, rect()));
  133. //Draws the given digits-pixmap at position (0, 0)
  134. p.end();
  135. }
  136. /*define a resize event*/
  137. void resizeEvent(QResizeEvent*) {
  138. preparePixmap();
  139. update();//Causes a paintEvent() call
  140. }
  141. /*Paint the static state*/
  142. void paintStatic() {
  143. QPainter p(this);
  144. p.fillRect(rect(), Qt::black);
  145. //Fill the widget rec with black color
  146. int pad = width() / 10;
  147. drawFrame(&p, rect().adjusted(pad, pad, -pad, -pad));
  148. p.drawPixmap(0, 0, m_pixmap);
  149. }
  150. /*Paint the slide state*/
  151. void paintSlide() {
  152. QPainter p(this);
  153. p.fillRect(rect(), Qt::black);
  154. int pad = width() / 10;
  155. QRect fr = rect().adjusted(pad, pad, -pad, -pad);
  156. drawFrame(&p, fr);
  157. p.setClipRect(fr);
  158. //sets the clip region to the given rectangle using the given clip operation
  159. int y = height() * m_animator.currentFrame() / 100;
  160. p.drawPixmap(0, y, m_lastPixmap);
  161. //Draw last-time state pixmap from 0 to height()(Y Coordinate)  in 0.6 second
  162. p.drawPixmap(0, y - height(), m_pixmap);
  163. //Draw current-time state pixmap from -height() to 0 (Y Coordinate) in 0.6 second
  164. }
  165. /*Paint the flip state*/
  166. void paintFlip() {
  167. QPainter p(this);
  168. #if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_WINCE_WM)
  169. p.setRenderHint(QPainter::SmoothPixmapTransform, true);
  170. p.setRenderHint(QPainter::Antialiasing, true);
  171. #endif
  172. p.fillRect(rect(), Qt::black);
  173. int hw = width() / 2;
  174. int hh = height() / 2;
  175. // behind is the new pixmap
  176. int pad = width() / 10;
  177. QRect fr = rect().adjusted(pad, pad, -pad, -pad);
  178. drawFrame(&p, fr);
  179. p.drawPixmap(0, 0, m_pixmap);
  180. int index = m_animator.currentFrame();
  181. if (index <= 50) {
  182. // the top part of the old pixmap is flipping
  183. int angle = -180 * index / 100;
  184. QTransform transform;
  185. transform.translate(hw, hh);
  186. //Moves the coordinate system to the center of widget
  187. transform.rotate(angle, Qt::XAxis);
  188. //Rotates the coordinate system counterclockwise by angle about the X axis
  189. p.setTransform(transform);
  190. drawFrame(&p, fr.adjusted(-hw, -hh, -hw, -hh));
  191. p.drawPixmap(-hw, -hh, m_lastPixmap);
  192. // the bottom part is still the old pixmap
  193. p.resetTransform();
  194. p.setClipRect(0, hh, width(), hh);
  195. //Enables clipping, and sets the clip region to the rectangle beginning at (0, hh) with the given width and height
  196. drawFrame(&p, fr);
  197. p.drawPixmap(0, 0, m_lastPixmap);
  198. } else {
  199. p.setClipRect(0, hh, width(), hh);
  200. // the bottom part is still the old pixmap
  201. drawFrame(&p, fr);
  202. p.drawPixmap(0, 0, m_lastPixmap);
  203. // the bottom part of the new pixmap is flipping
  204. int angle = 180 - 180 * m_animator.currentFrame() / 100;
  205. QTransform transform;
  206. transform.translate(hw, hh);
  207. transform.rotate(angle, Qt::XAxis);
  208. p.setTransform(transform);
  209. drawFrame(&p, fr.adjusted(-hw, -hh, -hw, -hh));
  210. p.drawPixmap(-hw, -hh, m_pixmap);
  211. }
  212. }
  213. /*Paint the rotate state*/
  214. void paintRotate() {
  215. QPainter p(this);
  216. int pad = width() / 10;
  217. QRect fr = rect().adjusted(pad, pad, -pad, -pad);
  218. drawFrame(&p, fr);
  219. p.setClipRect(fr);
  220. int angle1 = -180 * m_animator.currentFrame() / 100;
  221. int angle2 = 180 - 180 * m_animator.currentFrame() / 100;
  222. int angle = (m_animator.currentFrame() <= 50) ? angle1 : angle2;
  223. QPixmap pix = (m_animator.currentFrame() <= 50) ? m_lastPixmap : m_pixmap;
  224. QTransform transform;
  225. transform.translate(width() / 2, height() / 2);
  226. transform.rotate(angle, Qt::XAxis);
  227. p.setTransform(transform);
  228. p.setRenderHint(QPainter::SmoothPixmapTransform, true);
  229. p.drawPixmap(-width() / 2, -height() / 2, pix);
  230. }
  231. void paintEvent(QPaintEvent *event) {
  232. Q_UNUSED(event);
  233. if (m_animator.state() == QTimeLine::Running) {
  234. if (m_transition == Slide)
  235. paintSlide();
  236. if (m_transition == Flip)
  237. paintFlip();
  238. if (m_transition == Rotate)
  239. paintRotate();
  240. } else {
  241. paintStatic();
  242. }
  243. }
  244. private:
  245. int m_number;//number to set to digits
  246. int m_transition;//transition mode(change effect)
  247. QPixmap m_pixmap;//current time pixmap
  248. QPixmap m_lastPixmap;//next state time pixmap
  249. QTimeLine m_animator;
  250. //used to animate a GUI control by calling a slot periodically
  251. //The timeline's duration describes for how long the animation will run
  252. //connect the frameChanged() signal to a suitable slot in the widget you wish to animate
  253. };
  254. class DigiFlip : public QMainWindow
  255. {
  256. Q_OBJECT
  257. public:
  258. DigiFlip(QWidget *parent = 0)
  259. : QMainWindow(parent)
  260. {
  261. m_hour = new Digits(this);
  262. m_hour->show();
  263. m_minute = new Digits(this);
  264. m_minute->show();
  265. QPalette pal = palette();
  266. pal.setColor(QPalette::Window, Qt::black);
  267. //Sets the color used for the given color role, in all color groups, to the specified solid color.
  268. setPalette(pal);
  269. m_ticker.start(1000, this);
  270. //Send a timer event every second
  271. QTime t = QTime::currentTime();
  272. m_hour->setNumber(t.hour());
  273. m_minute->setNumber(t.minute());
  274. updateTime();
  275. QAction *slideAction = new QAction("&Slide", this);
  276. QAction *flipAction = new QAction("&Flip", this);
  277. QAction *rotateAction = new QAction("&Rotate", this);
  278. connect(slideAction, SIGNAL(triggered()), SLOT(chooseSlide()));
  279. connect(flipAction, SIGNAL(triggered()), SLOT(chooseFlip()));
  280. connect(rotateAction, SIGNAL(triggered()), SLOT(chooseRotate()));
  281. #if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM)
  282. menuBar()->addAction(slideAction);
  283. menuBar()->addAction(flipAction);
  284. menuBar()->addAction(rotateAction);
  285. #else
  286. addAction(slideAction);
  287. addAction(flipAction);
  288. addAction(rotateAction);
  289. setContextMenuPolicy(Qt::ActionsContextMenu);
  290. //Shows a context menu(right click)
  291. #endif
  292. }
  293. /*Real-time updates*/
  294. void updateTime() {
  295. QTime t = QTime::currentTime();
  296. m_hour->flipTo(t.hour());
  297. m_minute->flipTo(t.minute());
  298. QString str = t.toString("hh:mm:ss");
  299. str.prepend(": ");
  300. if (m_hour->transition() == Digits::Slide)
  301. str.prepend("Slide");
  302. if (m_hour->transition() == Digits::Flip)
  303. str.prepend("Flip");
  304. if (m_hour->transition() == Digits::Rotate)
  305. str.prepend("Rotate");
  306. setWindowTitle(str);
  307. }
  308. /*Switch transition mode*/
  309. void switchTransition(int delta) {
  310. int i = (m_hour->transition() + delta + 3) % 3;
  311. m_hour->setTransition(i);
  312. m_minute->setTransition(i);
  313. updateTime();
  314. }
  315. protected:
  316. void resizeEvent(QResizeEvent*) {
  317. int digitsWidth = width() / 2;
  318. int digitsHeight = digitsWidth * 1.2;
  319. int y = (height() - digitsHeight) / 3;
  320. m_hour->resize(digitsWidth, digitsHeight);
  321. m_hour->move(0, y);
  322. m_minute->resize(digitsWidth, digitsHeight);
  323. m_minute->move(width() / 2, y);
  324. }
  325. /*Timer event,receive timer events */
  326. void timerEvent(QTimerEvent*) {
  327. updateTime();
  328. }
  329. /* Get key press event */
  330. void keyPressEvent(QKeyEvent *event) {
  331. if (event->key() == Qt::Key_Right) {
  332. switchTransition(1);
  333. event->accept();
  334. }
  335. if (event->key() == Qt::Key_Left) {
  336. switchTransition(-1);
  337. event->accept();
  338. }
  339. }
  340. private slots:
  341. void chooseSlide() {
  342. m_hour->setTransition(0);
  343. m_minute->setTransition(0);
  344. updateTime();
  345. }
  346. void chooseFlip() {
  347. m_hour->setTransition(1);
  348. m_minute->setTransition(1);
  349. updateTime();
  350. }
  351. void chooseRotate() {
  352. m_hour->setTransition(2);
  353. m_minute->setTransition(2);
  354. updateTime();
  355. }
  356. private:
  357. QBasicTimer m_ticker;
  358. Digits *m_hour;
  359. Digits *m_minute;
  360. };
  361. #include "digiflip.moc"
  362. int main(int argc, char *argv[])
  363. {
  364. QApplication app(argc, argv);
  365. DigiFlip time;
  366. //#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM)
  367. //  time.showFullScreen();
  368. //#else
  369. time.resize(320, 240);
  370. time.show();
  371. //#endif
  372. return app.exec();
  373. }

以下为程序截图:

http://blog.csdn.net/huihui1988/article/details/5853728#comments

Qt仿Android带特效的数字时钟源码分析(滑动,翻页,旋转效果)的更多相关文章

  1. [Android实例] Scroll原理-附ScrollView源码分析

    想象一下你拿着放大镜贴很近的看一副巨大的清明上河图, 那放大镜里可以看到的内容是很有限的, 而随着放大镜的上下左右移动,就可以看到不同的内容了 android中手机屏幕就相当于这个放大镜, 而看到的内 ...

  2. [Android实例] Scroll原理-附ScrollView源码分析 (转载)

    想象一下你拿着放大镜贴很近的看一副巨大的清明上河图, 那放大镜里可以看到的内容是很有限的, 而随着放大镜的上下左右移动,就可以看到不同的内容了 android中手机屏幕就相当于这个放大镜, 而看到的内 ...

  3. Android Activity Deeplink启动来源获取源码分析

    一.前言 目前有很多的业务模块提供了Deeplink服务,Deeplink简单来说就是对外部应用提供入口. 针对不同的跳入类型,app可能会选择提供不一致的服务,这个时候就需要对外部跳入的应用进行区分 ...

  4. Android应用层View绘制流程与源码分析

    1  背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原 ...

  5. Android Telephony —— 手机信号实时变化源码分析过程记录

    源码版本:4.4 跳过InCallActivity等UI实现.先看service以及底层. 1, 在frameworks/opt下面会发现如下文件列表: ./telephony/src/java/co ...

  6. 【Android 界面效果45】ViewPager源码分析

    ViewPager概述: Layout manager that allows the user to flip left and right through pages of data. You s ...

  7. 转 Android的消息处理机制(图+源码分析)——Looper,Handler,Message

    作为一个大三的预备程序员,我学习android的一大乐趣是可以通过源码学习google大牛们的设计思想.android源码中包含了大量的设计模式,除此以外,android sdk还精心为我们设计了各种 ...

  8. 【转】android的消息处理机制(图+源码分析)——Looper,Handler,Message

    原文地址:http://www.cnblogs.com/codingmyworld/archive/2011/09/12/2174255.html#!comments 作为一个大三的预备程序员,我学习 ...

  9. android的消息处理机制(图+源码分析)——Looper,Handler,Message

    android源码中包含了大量的设计模式,除此以外,android sdk还精心为我们设计了各种helper类,对于和我一样渴望水平得到进阶的人来说,都太值得一读了.这不,前几天为了了解android ...

随机推荐

  1. Could not open a connection to your authentication agent

    执行ssh-add ~/.ssh/rsa  就会遇到上述错误了 解决方案: 先执行  eval `ssh-agent`  (是-键上的那个`) 再执行 ssh-add ~/.ssh/rsa成功 ssh ...

  2. Android模仿微信语音聊天功能

    项目效果如下: 项目目录结构如下: 代码如下: AudioManager.java import java.io.File; import java.io.IOException; import ja ...

  3. 一次处理ORA-07445的历险记(转)

    ORA-07445通常是Oracle调用操作系统的资源出错时出现的[@more@] 事前没有任何征兆,下午5点左右某个关键应用的17台oracle数据库上的数据库实例陆续宕机,赶紧查看alert_lo ...

  4. Lowest Common Ancestor of a Binary Search Tree 解答

    Question Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes ...

  5. 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅵ

    · 学后心得体会与部分习题实现 心得体会: 曾经只是了解了优先队列的基本性质,并会调用C++ STL库中的priority_queue以及 java.util.PriorityQueue<E&g ...

  6. 飘逸的python - 性能调优利器profile及其意义

    VIM 的作者Bram Moolenaar在一篇叫高效文本编辑器的7个习惯的ppt中有这么一段话. Three basic steps 1.    Detect inefficiency 2.    ...

  7. 浅谈C++调用C#的DLL程序方法

    把C#编译成DLL或者Axtive控件,再由C调用!比如使用C++调用C#的DLL. SwfDotNet是.net下输出flash的类库.SwfDotNet是C#编写的,作者的C#水平,真是令我佩服. ...

  8. 人物角色群体攻击判定(三)Physics.OverlapSphere(群体攻击)

    使用Physics.OverlapSphere来检测不方便调试, 其他都可以.   核心代码: //检测敌人 public void CheckEnemy() { Collider[] cols = ...

  9. c++之 变量

    变量的基本操作 变量就是一个可以变化的量,变量由变量类型.变量名.初始值(可选)组成,例如: int abc = 10; 变量类型:int 变量名:abc 初始值:10 // 该值为可选项,在创建变量 ...

  10. Xcode5和6上新建工程如何本地化启动页面

    建议阅读本篇文章前先具备iOS本地化的基本知识,Google中搜索“iOS本地化”,有成片的教程~~ 最近有个app需要支持英语.简体中文.繁体中文,由于启动页面上有文字,所以也不得不做下本地化处理. ...