zoukankan      html  css  js  c++  java
  • Qt仿Android带特效的数字时钟源码分析(滑动,翻页,旋转效果)

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

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

    以下为源码:

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

    以下为程序截图:

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

  • 相关阅读:
    铁乐学Python_Day35_Socket模块3和hmac模块
    铁乐学Python_Day34_Socket模块2和黏包现象
    铁乐学Python_Day33_网络编程Socket模块1
    铁乐学python_day29_模块与包学习4
    铁乐学python_day28_模块学习3
    铁乐学python27_模块学习2
    铁乐学python_md5校验两个文件的一致性
    铁乐学python26_hashlib+configparser+logging模块
    Flask与Ajax
    Javascript与Ajax
  • 原文地址:https://www.cnblogs.com/findumars/p/4973147.html
Copyright © 2011-2022 走看看