基于qt实现网易云界面轮播效果实现

基于qt实现网易云音乐的轮播效果


网易云轮播效果

前言

其实主要是想做点记录吧,本人比较喜欢音乐,所以在上周决定在搭建一个网易云的界面框架,不做不知道,做了才发现qt还有很多的框架是自己不太熟悉的。


一、准备

1.1.想要做好这个界面我感觉graphicsView以及的了解是必不可少的。因为在qt画图功能上与QPainter实现画图比,graphicsView功能反而就变得就更强大了。查阅了相关的博客:
1.1.1.Qt之QGraphicsView入门篇
1.1.2.Qt之QGraphicsView进阶篇
1.1.3.Qt之QGraphicsView实战篇
这三个博客我感觉写的其实挺好,也是带我初步了解GraphicsView。
1.2那么知道了QGraphicsView,怎么实现网易云的轮播效果呢?
1.2.1我感觉在QGraphicsView画布上主要关注的几点是:

  • 图片的位置
  • 图片的优先级(轮播效果中存在缩放效果)
  • 图片的大小情况
  • 轮播时的轮换效果
  • 图片与按钮之间的映射
  • 图片的轮播切换

这些是必不可少的。其中我参考了

二、实现

1.图片的的读取,位置,大小以及按钮映射图片的实现

代码如下(示例):
.h里面

void init();

    qreal getOffset(int pictureNum);
    int   getZValue(int pictureNum);

    void setPictureItem(int picId);
    double getScaled(int num);
    void setBtnGroup();

    int getPictureNum(int id);
    int getrightN(int num);

    QGraphicsScene * m_scene;
    QLineF m_lineF;
    QVector<PictureItem*> m_pictures;

    QList<QPointF> m_pointA;
    QButtonGroup *m_BtnGroup;


    QMap<int,PictureItem*> m_mapBtnToPicture;
 

.cpp里面


```#define POINT_SIST_FISRT 0
// 图片的位置
#define POINT_SIST_SECEND 0.15
#define POINT_SIST_OTHER 0.45

#define PICTURENUM 10 //图片的数量

#define SCALE_VIEW_PIXMAP (qreal)1/1 //View与图片比例

#define RAW_VIEW_SIZE QSize(950,198) //场景大小

//图片缩放大小
#define SCALEMIN 0.8	
#define SCALEMAX 1


#define POINT_SIST_FISRT 0
#define POINT_SIST_SECEND 0.15
#define POINT_SIST_OTHER 0.45
 // 初始化图片属性
 m_lineF.setPoints(QPointF(0,0),
                   QPointF(this->width(),0));
                   for(int i =0
 for(int i = 0; i < PICTURENUM; ++i)
    {
    	// 给每个图片Item添加图片
        QPixmap pixmap(QString("./images/picturewall/%1.png").arg(i + 1));
        // 设置图片大小
        pixmap.scaled(RAW_VIEW_SIZE / SCALE_VIEW_PIXMAP,
                                                 Qt::KeepAspectRatio,Qt::FastTransformation);
        PictureItem * nn = new PictureItem(pixmap);
        m_pictures.append(nn);
        // 设置图片的位置
        QPointF point =m_lineF.pointAt(getOffset(i));
        m_pictures.at(i)->setPos(point);

		//设置图片的优先级
        m_pictures.at(i)->setZValue(getZValue(i));

		// 用于后面的轮播相当于id
        m_pictures.at(i)->setType(i);

		// 因为中间的图片要设置为最大,所以在这做了一个判断来让第二张图片最大化
        if(i == 1)
        {
            m_pictures.at(i)->setScale(SCALEMAX);
        }
        else
        {
             m_pictures.at(i)->setScale(SCALEMIN);
             m_pictures.at(i)->setPos(m_pictures.at(i)->x(),(RAW_VIEW_SIZE.height() / 10));
        }
        // 把各个图片都加入到scene里面
        m_scene->addItem(m_pictures.at(i));
        m_pointA.append(m_pictures[i]->pos());
		// 关联按钮,做一个map的映射
        m_mapBtnToPicture.insert(static_cast<PictureButton*>(m_BtnGroup->button(i))->getId(),m_pictures[i]);
    }
	// 设置按钮的初始化的对应的图片
    m_curBtnId = 1;
}
 

其中getOffset就是给对应的图片加上对应的位置,因为界面上必定有三张图片是显示在界面上的,其他都是被覆盖的情况

qreal PictureRollWgt::getOffset(int pictureNum)
{
    switch (pictureNum) {
    case 0:
        return POINT_SIST_FISRT;
    case 1:
        return POINT_SIST_SECEND;
    case 2:
        return POINT_SIST_OTHER;
    default:
        return POINT_SIST_SECEND;
    }
}


其中的getScaled就是设置对应图片的缩放效果,只有其中一张图片是最大的其他都是小图片

double PictureRollWgt::getScaled(int num)
{
    if(num == 1)
        return SCALEMAX;
    else
        return SCALEMIN;
}

getZValue表示图片优先级,显示的图片优先级分别是1,2,1,其他都是0;

int PictureRollWgt::getZValue(int pictureNum)
{
    switch (pictureNum) {
    case 0:
        return 1;
    case 1:
        return 2;
    case 2:
        return 1;
    default:
        return 0;
    }
}

这样就可以初步完成界面的效果了

2.完成动态效果

动态效果主要分为三种情况,

  1. 按钮切换
  2. 计时器切换
  3. 图片下面的鼠标进入到小Btn来切换

上面已经做了图片与按钮的映射,但是怎么实现这3种场景呢?

  1. 首先说一种就是图片下面的鼠标进入到小Btn来切换,当鼠标进入到小按钮内部就需要切换对应的图片到中间,做主图。因此普通QPushButton是实现不了的。所以必须要自定义按钮。也就是继承一个QAbstractButton类来实现对应的信号与槽以及重写鼠标进入事件,其中主要代码如下:
void PictureButton::enterEvent(QEvent *event)
{
    if(!isChecked())
        setChecked(true);
    emit sigEntered(m_id);
    return QAbstractButton::enterEvent(event);
}

这样就可以发送一个信号到主界面做出响应

2.关键逻辑部分,就是在做到按钮与图像item的映射后就可以去做到切换图片功能,这里主要是重新排序图片容器,QGraphicsItemAnimation与QTimeLine 都是用来实现动态效果。

void PictureRollWgt::setPictureItem(int picId)
{
    QVector<QGraphicsItemAnimation*> items(10);//用于去做图片动态

    for(int i = 0; i < 10; ++i)
    {
        items[i] = new QGraphicsItemAnimation;
    }
    QTimeLine *timeline = new QTimeLine(200);
    timeline->setLoopCount(1);
    int pic = getrightN(picId - 1);
    qDebug() << pic;
    for(int i = 0; i < 10; ++i)
    {
        m_pictures[i] = m_mapBtnToPicture.value(pic % 10);
        pic++;
        m_pictures[i]->setScale(getScaled(i));
        m_pictures[i]->setZValue(getZValue(i));
        m_pictures[i]->setTransformationMode(Qt::SmoothTransformation);//设置缩放模式

        items[i]->setItem(m_pictures[i]);
        items[i]->setTimeLine(timeline);
        items[i]->setPosAt(0.5,m_pointA[i]);
    }
    timeline->start();
    m_scene->invalidate();
    items.clear();

}

总结

在实现网易云界面的界面上还有很多东西需要搭建。在实现轮播图时多亏了比卡丘不皮的网易云源代码以及博客
里面很多内容都是参考了他的,以及图片。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值