手把手教你开发-滚动效果号码抽奖(QT)

本文从头开发教你开发一个带滚动效果的抽奖软件。最终效果如下:

源码在文章最后

手把手教你开发-滚动效果号码抽奖(QT)

软件开发的第一步是需求分析,其实好的开发人员就是半个产品经理,我相信很多开发者都被产品经理坑过,需求一变再变,所以我们要在开发之前就把需求问清楚,越细越完善越好,尤其是面对领导编程的时候更加需要把需求明确下来。

正确的方向才会得到正确的结果,错误的方向再怎么努力也不会有好的结果。

一、需求分析

不知道你遇到过这样的需求吗?通常是一句话,在这个抽奖软件中,客户也只是给了一句话:“我想要一个带滚动效果的抽奖,在晚会上面使用。”

如果只是满足他的这个一句话的需求,那么软件开发完成客户肯定不会满意。我们需要在开发之前确定一些隐藏的功能点。

例如:

1、需不需要音乐?背景音乐和滚动音乐。

这个项目案例中未开发,但是实际场景中肯定是需要的。

2、抽奖的触发方式是什么?有没有额外的硬件按钮、鼠标控制还是键盘控制。

这个项目案例未开发,但是实际场景中可以需要适配硬件按钮,蓝牙或者无线等通信触发。

3、需要不需要指定中将号码?

开发过抽奖的软件的工程师一般都不会相信所谓的抽奖软件了。

项目中开发了该功能。

4、需要不需要将抽奖数据保存在文件中?

这个功能是肯定需要的,项目中预留的保存数据接口。

5、字体颜色会随时改变吗?

使用过程中,客户有时候会喜欢改变字体颜色显得更加高大上,尤其是户外的显示屏的颜色和开发过程中的效果可能不一样,因此可能需要针对具体的显示屏和环境进行调整背景图片以及颜色。

项目中预留了颜色调整的接口。

二、软件设计

有了需求其实就可以针对需求进行设计。

框架设计

软件框架图如下:

手把手教你开发-滚动效果号码抽奖(QT)

 RollingLotteryView : 抽奖窗口类,主要管理抽奖停止循序,已经抽奖的背景图等。

NumItem:抽奖号码类,每个抽奖号码的管理,号码滚动效果都在这里类中完成。

接口:

接口    说明

setItemBackground(QImage img)

设置每一个抽奖号码的背景

bool setItemColor(QColor color)

设置抽奖号码的颜色

bool setBackground(QImage img)

设置整体的大背景图

void start()

开始抽奖
void stop(int res=-1) 结束抽奖,如果设置数据那么会在指定的数据下停止

void sigStop(int num)

信号,抽奖结束后会触发该信号,

用户可以通过绑定该信号获取抽奖结果

流程设计

用户调用start接口,触发每一个num_item的定时器,然后让每一个号码转动起来。启动流程如下:

手把手教你开发-滚动效果号码抽奖(QT)

暂停流程比较复杂,因为需要逐个停止,因此每一个停止之后需要告诉主页面触发下一个号码的停止,流程图如下:

 手把手教你开发-滚动效果号码抽奖(QT)

 关键算法

void NumItem::on_timer_timeout()
{
    // 数字号码的高度。
    m_height += 5;
    QFont qf;
    qf.setPointSize(2);
    qf.setPixelSize(100);
    QFontMetrics qfm(qf);
    int b = qfm.height(); // 计算字高
    // 当移动高度大于字体高度的时候认为该字体已经被隐藏掉了
    if (m_height > b) {
        m_height = m_height % b;
        // 数字循环
        if (m_num == 0) {
            m_num = 9;
        }
        else {
            m_num--;
        }   
       
        if (!m_status) {
             // 是否指定了结果,如果指定结果那么就行等到指定的结果才停止。
            if(m_resNum == -1){
                sigStop(m_num);
                m_timer->stop();
            }
            else if(m_resNum == m_num){
                sigStop(m_num);
                m_timer->stop();
            }
        }
    }
    update();
}
void NumItem::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    QFont qf;
    QPen pen(m_color);
    p.setPen(pen);
    qf.setPointSize(2);
    qf.setPixelSize(100);
    QFontMetrics qfm(qf);
    int a = qfm.width("1");
    int b = qfm.height();
    p.setFont(qf);
    // 由于要做滚动效果,因此需要画两个字
    // 由于高度不断的变高,那么呈现出滚动的效果。
    p.drawText(0, m_height, a, b, 1, QString::number(m_num));
    p.drawText(0, m_height - b, a, b, 1, QString::number(m_num - 1));
    if (m_imgBackground.isNull()) {
        return;
    }
    QPainter painter(this);
    QRect target(0, 0, this->size().width(), this->size().height());
    painter.drawImage(target, m_imgBackground);
}

git源码传送门

上一篇:Qt源码解析4-事件系统


下一篇:用Qt命令行工具打包程序