当前位置: 首页 > ds >正文

QT项目 -仿QQ音乐的音乐播放器(第三节)

目录

自定义recBox:

RecBoxItem类中添加动画效果:

两个添加TEXT和imgStyle的函数:

图片随机函数:

qqmusic.cpp:

recbox的初始化函数:

QT的一些额外加餐:

关于如何设置按钮的功能

connect函数

事件过滤器:实现监视目标对象事件 的作用

QPropertyAnimation的基本使用

QString

QJsonArray和QJsonObject

 

自定义recBox:

1. RecBox界⾯布局
① 新添加设计师界⾯,命名为RecBox。geometry的宽⾼修改为:685*440。
② 添加三个Widget,objectName依次修改为leftPage、musicContent、rightPage;
leftPage 和 rightPage的minimumSize和maximumSize修改宽为30,然后选中RecBox点击⽔平布
局。将RecBox的 margin和Spacing修改为0
③ 在upPage和downPage中各拖⼀个按钮,upPage中按钮objectName修改为btUp,minimumSize
的⾼度修改为 220;downPage中按钮objectName修改为btDown,minimumSize的⾼度修改为
220;然后选中upPage和 downPage点击⽔平布局。将upPagedownPage和的margin和
Spacing修改为0。
③ 在musicContent中拖两个Widget,objectName依次修改为recListUp和recListDown,然后选中
musicContent点 击垂直布局,将musicContent的margin和Spacing修改为0。(为了看清楚效果可
临时将recListUp背景⾊设置 为:background-color:green; 将recListDown背景⾊设置为:
background-color:red;)
④ 在recListUp和recListDown中分别拖两个⽔平布局器,依次命名为recListUpHLayout和
recListDownHLayout,选 中recListUp和recListDown点击⽔平布局,将margin和Spacing修改为0
做好美化后将QQMusic主界⾯中recPage⻚⾯中的recMusicBox和supplyMusicBox提升为RecBox


RecBoxItem类中添加动画效果:

重写eventfilter函数

bool RecBoxItem::eventFilter(QObject *watched, QEvent *event)
{if(watched == ui->musicImageBox){if(QEvent::Enter == event->type()){// 添加图片上移动画QPropertyAnimation* animation = new QPropertyAnimation(ui->musicImageBox, "geometry");animation->setDuration(150);animation->setStartValue(QRect(9,9, ui->musicImageBox->width(), ui->musicImageBox->height()));animation->setEndValue(QRect(9, 0, ui->musicImageBox->width(), ui->musicImageBox->height()));animation->start();connect(animation, &QPropertyAnimation::finished, this, [=](){delete animation;});}else if(QEvent::Leave == event->type()){// 添加图标下移动画QPropertyAnimation* animation = new QPropertyAnimation(ui->musicImageBox, "geometry");animation->setDuration(150);animation->setStartValue(QRect(9,0, ui->musicImageBox->width(), ui->musicImageBox->height()));animation->setEndValue(QRect(9, 9, ui->musicImageBox->width(), ui->musicImageBox->height()));animation->start();connect(animation, &QPropertyAnimation::finished, this, [=](){delete animation;});}return true;}return QObject::eventFilter(watched, event);
}

两个添加TEXT和imgStyle的函数:

void RecBoxItem::setText(const QString &text)
{ui->recBoxItemText->setText(text);
}void RecBoxItem::setImage(const QString &Imagepath)
{QString imgStyle="border-image:url("+Imagepath+");";ui->recMusicImage->setStyleSheet(imgStyle);
}

图片随机函数:

在qqmusic.cpp中定义图片随机选取并且存成嵌套qjsonobject的qjsonarray格式返回,后面会在qqmusic调用initrecitem函数,里面randompicture的返回值会作为参数。

QJsonArray QQMusic::RandomPicture()
{// 推荐⽂本 + 推荐图⽚路径QVector<QString> vecImageName;vecImageName<<"001.png"<<"003.png"<<"004.png"<<"005.png"<<"006.png"<<"007.png"<<"008.png"<<"009.png"<<"010.png"<<"011.png"<<"012.png"<<"013.png"<<"014.png"<<"015.png"<<"016.png"<<"017.png"<<"018.png"<<"019.png"<<"020.png"<<"021.png"<<"022.png"<<"023.png"<<"024.png"<<"025.png"<<"026.png"<<"027.png"<<"028.png"<<"029.png"<<"030.png"<<"031.png"<<"032.png"<<"033.png"<<"034.png"<<"035.png"<<"036.png"<<"037.png"<<"038.png"<<"039.png"<<"040.png";std::random_shuffle(vecImageName.begin(), vecImageName.end());// 001.png// path: ":/images/rec/"+vecImageName[i];// text: "推荐-001"QJsonArray objArray;for(int i = 0; i < vecImageName.size(); ++i){QJsonObject obj;obj.insert("path", ":/images/rec/"+vecImageName[i]);// arg(i, 3, 10, QCchar('0'))// i:要放⼊%1位置的数据// 3: 三位数// 10:表⽰⼗进制数// QChar('0'):数字不够三位,前⾯⽤字符'0'填充QString strText = QString("推荐-%1").arg(i, 3, 10, QChar('0'));obj.insert("text", strText);objArray.append(obj);}return objArray;}
recbox.h:#ifndef RECBOX_H
#define RECBOX_H#include <QWidget>
#include <QJsonArray>namespace Ui {
class RecBox;
}class RecBox : public QWidget
{Q_OBJECTpublic:explicit RecBox(QWidget *parent = nullptr);~RecBox();void initRecBoxUi(QJsonArray data, int row);//初始化推荐界面void createRecBoxItem();private:Ui::RecBox *ui;int row; // 记录当前RecBox实际总⾏数int col; // 记录当前RecBox实际每⾏有⼏个元素QJsonArray imageList; // 保存界⾯上的图⽚, ⾥⾯实际为key、value键值对};#endif // RECBOX_H

 

上面在recbox.h中定义了row和col作为行列

qqmusic.cpp:

    srand(time(NULL));ui->recMusicBox->initRecBoxUi(RandomPicture(),1);ui->supplyMusicBox->initRecBoxUi(RandomPicture(),2);

在recbox的构造函数里初始化行列数值

#include "ui_recbox.h"
#include<RecBoxItem.h>
#include <QJsonObject>RecBox::RecBox(QWidget *parent): QWidget(parent), ui(new Ui::RecBox),row(1),col(4)
{ui->setupUi(this);
}

recbox的初始化函数:

recbox.cppvoid RecBox::initRecBoxUi(QJsonArray data, int row)
{// 如果是两⾏,说明当前RecBox是主界⾯上的supplyMusicBoxif(2 == row){this->row = row;this->col = 8;}else{// 否则:只有⼀⾏,为主界⾯上recMusicBoxui->recListDown->hide();}// 图⽚保存起来imageList = data;// 往RecBox中添加图⽚createRecBoxItem();
}void RecBox::createRecBoxItem()
{// 创建RecBoxItem对象,往RecBox中添加// colfor(int i = 0; i < col; ++i){RecBoxItem* item = new RecBoxItem();// 设置⾳乐图⽚与对应⽂本QJsonObject obj = imageList[i].toObject();item->setText(obj.value("text").toString());item->setImage(obj.value("path").toString());// recMusicBox:col为4,元素添加到ui->recListUpHLayout中// supplyMuscBox: col为8, ui->recListUpHLayout添加4个,ui->recListDownHLayout添加4个// 即supplyMuscBox上下两⾏都要添加// 如果是recMusicBox:row为1,只能执⾏else,所有4个RecBoxItem都添加到ui->recListUpHLayout中// 如果是supplyMuscBox:row为2,col为8,col/2结果为4,i为0 1 2 3时,元素添加到ui->recListDownHLayout中// i为4 5 6 7时,元素添加到ui->recListUpHLayout中if(i >= col/2 && row == 2){ui->recListDownHLayout->addWidget(item);}else{ui->recListUpHLayout->addWidget(item);}}}

 

总结下来就是在recboxitem类里重写eventfilter函数设置动画,然后在recbox函数里添加图片/写初始化图片函数,在qqmusic类里写随机图片函数(输出json格式的array数组),在qqmusic类里调用初始化图片函数。

 

最后的效果:

 

QT的一些额外加餐:

 

关于如何设置按钮的功能

1.手动添加槽函数
2.定义类然后在相应的Widget位置提升为新的类
3.直接在cpp中实例化类然后添加ui
RecBoxItem* item = new RecBoxItem();
ui->recListUpHLayout->addWidget(item);
4.用connect函数连接
下面介绍connect函数

connect函数

信号槽机制,按钮是发送信号,窗口是接收信号,槽的本质就是对信号响应的函数,是一个回调函数

例1:

void QQMusic::connectSignalAndSlot()
{connect(ui->Rec, &BtForm::click, this, &QQMusic::onBtFormClick);connect(ui->music, &BtForm::click, this, &QQMusic::onBtFormClick);connect(ui->audio, &BtForm::click, this, &QQMusic::onBtFormClick);connect(ui->like, &BtForm::click, this, &QQMusic::onBtFormClick);connect(ui->local, &BtForm::click, this, &QQMusic::onBtFormClick);connect(ui->recent, &BtForm::click, this, &QQMusic::onBtFormClick);
}  

这里连接了6个`BtForm`类型按钮(`ui->Rec`, `ui->music`, `ui->audio`, `ui->like`, `ui->local`, `ui->recent`)的`click`信号到当前对象(`this`,即`QQMusic`实例)的同一个槽函数`onBtFormClick`。- 这意味着当这些按钮中的任何一个被点击时,都会触发`QQMusic::onBtFormClick`槽函数。

 

这里的第一个参数是目标对象界面中的按钮组件),第二个参数是触发信号自定义按钮类 BtForm 的点击信号),第三个参数接收者当前 QQMusic 类实例),第四个参数槽函数处理按钮点击的槽函数

 

例2:

connect(animation, &QPropertyAnimation::finished, this, [=](){delete animation;
});

这里连接了一个`QPropertyAnimation`对象(指针变量名为`animation`)的`finished`信号。- 当动画完成时,会触发一个Lambda表达式(作为槽函数)。- Lambda表达式以值捕获方式(`[=]`)捕获当前作用域的变量(注意:这里捕获的是`this`指针和`animation`指针,因为`animation`在外部定义)。- 在Lambda表达式内部,执行`delete animation;`,即删除动画对象,释放内存。

这里的第一个参数是针对musicImageBox创建的动画组件,第二个参数是结束触发信号,第三个参数是接收者this(recboxitem),第四个参数是槽函数(删除动画)

事件过滤器:实现监视目标对象事件 的作用

bool eventFilter(QObject *watched, QEvent *event);
 eventFilter 的第一个参数 obj 指向的是事件本应传递到的目标对象。
重写是类似这样的:
 bool Widget::eventFilter(QObject *obj, QEvent *event){if(obj == ui->label){//鼠标进入的时候if (event->type() == QEvent::Enter){ui->label->setText("我是红色");ui->label->setStyleSheet(redStyle);return true; //拦截事件,不再传递}else if(event->type() == QEvent::Leave) //鼠标离开{ui->label->setText("我是黑色");ui->label->setStyleSheet(blackStyle);return true;}return false;  //不拦截事件,允许继续传递,别的事件会传给label对象}// standard event processingreturn QWidget::eventFilter(obj, event);}

鼠标进入过滤->鼠标离开过滤

QPropertyAnimation的基本使用

常用接口函数

  • setTargetObject:设置仿真对象
  • setPropertyName:设置仿真属性的名称,
  • setDuration:设置仿真持续的时间
  • setStartValue:设置初始值
  • setEndValue:设置结束值
  • start:开始仿真
  • currentValue:返回当前值
  • setKeyValueAt:设置关键点的值
  • valueChanged:只要仿真追踪的值发生变化,就发送该信号

QString

QString 是 Qt 中的一个类,用于存储字符串,QString 没有父类。QString 存储的是一串字符,每个字符是一个 QChar 类型的数据。QChar 使用的是 UTF-16 编码,一个字符包含 2 字节数据。 对于超过 65535 的 Unicode 编码,QString 使用两个连续的 QChar 字符表示。UTF-16 是一种 Unicode 编码,能表示汉字,在 QString 字符串中一个汉字是一个字符。

 

QString 类定义了大量的接口函数用于字符串操作。QString在 Qt 类库中应用非常广泛,很多函数的参数是 QString 类型。

例如:

QString str = "Hello Qt";QString str1= "洋洋", str2= "得意"; 
QString str3= str1 + str2; //str3 ="洋洋得意" 
str1= str2 + str1; //str1 ="得意洋洋" QString str1= "卖", str2= "拐"; 
QString str3= str1; 
str1.append(str2); //str1 ="卖拐" 
str3.prepend(str2); //str3 ="拐卖" //等等还有好多函数

 

     

    RecBox添加RecBoxItem
    random_shuffle是打乱列表顺序的函数

     

    QJsonArray和QJsonObject

    这两个类都是用于处理JSON数据
    在Qt中,QJsonArray和QJsonObject是Qt JSON模块的一部分,用于表示JSON数据
    1. QJsonArray: - 功能:QJsonArray类用于封装一个JSON数组。 - 一个JSON数组是一个值的有序列表,这些值可以是不同的类型(包括字符串、数字、布尔值、对象、数组,以及null)。 - 在QJsonArray中,元素是通过索引(从0开始)来访问的。 - 常用操作: * 添加值:使用`append`、`push_back`或`insert`方法。 * 访问值:使用`at`方法或`operator[]`(注意:operator[]返回的是非const的引用,而at返回的是const引用)。 * 删除值:使用`removeAt`方法。 * 获取数组大小:使用`size`方法。 * 遍历:可以使用迭代器或简单的for循环(基于索引)。
    2. QJsonObject: - 功能:QJsonObject类用于封装一个JSON对象。 - 一个JSON对象是一个无序的键值对集合,其中键是字符串,值可以是各种JSON类型(包括数组、对象、基本类型等)。 - 在QJsonObject中,通过键(字符串)来访问对应的值。 - 常用操作: * 插入键值对:使用`insert`方法。 * 访问值:使用`value`方法或`operator[]`(注意:operator[]如果键不存在则会插入一个null值,而value方法不会修改对象)。 * 删除键值对:使用`remove`方法。 * 检查键是否存在:使用`contains`方法。 * 获取所有键:使用`keys`方法。 * 获取键值对数量:使用`size`方法。 * 遍历:可以使用迭代器或遍历键列表。
    QJsonArray:表示JSON数组,有序列表,通过索引访问。
    QJsonObject:表示JSON对象,键值对映射,通过键访问。
    例如:
    QJsonArray:QJsonArray arr;
    arr.append(42);          // 添加整数
    arr.append("Hello");     // 添加字符串
    arr.append(QJsonObject{ {"key", "value"} }); // 添加嵌套对象int num = arr[0].toInt();     // 获取索引 0 的值 → 42
    QString str = arr[1].toString(); // → "Hello"arr.replace(0, 100);     // 替换索引 0 的值
    arr.removeAt(1);         // 删除索引 1 的元素int size = arr.size();   // 获取元素数量
    bool isEmpty = arr.empty(); // 判空
    QJsonObject:QJsonObject obj;
    obj.insert("id", 1001);
    obj["name"] = "Alice";       // 使用运算符[]插入
    obj["scores"] = QJsonArray{90, 85, 95}; // 嵌套数组int id = obj["id"].toInt();          // → 1001
    QString name = obj.value("name").toString(); // → "Alice"obj["id"] = 2002;          // 修改值
    obj.remove("name");        // 删除键bool hasKey = obj.contains("scores"); // 检查键是否存在
    QStringList keys = obj.keys();      // 获取所有键 → ["id", "scores"]
    int size = obj.size();              // 键值对数量

     

     

     

    http://www.xdnf.cn/news/16733.html

    相关文章:

  • 基于dcmtk的dicom工具 第九章 以json文件或sqlite为数据源的worklist服务(附工程源码)
  • Qt 移动应用性能优化策略
  • 复现cacti的RCE(CVE-2022-46169)
  • TDengine 中 TDgpt 异常检测的机器学习算法
  • Leetcode——41. 缺失的第一个正数
  • 数学建模——非线性规划
  • 大文档免费翻译方法分享
  • 政策合规性前端设计:工业数据安全的可视化技术规范与落地实践
  • C语言进阶(指针2.函数指针和指针函数,二级指针,指针数组和数组指针,void*指针)
  • 数据结构 排序(2)---选择排序
  • 使用鼠标在Canvas上绘制矩形
  • PDF转Word免费工具!批量处理PDF压缩,合并, OCR识别, 去水印, 签名等全功能详解
  • Shader开发(四)计算机图形学中的颜色定义
  • Java 大视界 -- Java 大数据机器学习模型在金融信用评级模型优化与信用风险动态管理中的应用(371)
  • Day23-二叉树的层序遍历(广度优先搜素)
  • [明道云]-基础教学2-工作表字段 vs 控件:选哪种?
  • Redis 跨主机连接超时分析:从网络波动到架构优化
  • 个人健康管理小程序(消息订阅、Echarts图形化分析)
  • TGD第八篇:二维应用——图像边缘检测
  • ftp加ssl,升级ftps
  • 三维扫描相机:工业自动化的智慧之眼——迁移科技赋能智能制造新纪元
  • 从东南亚出发:小程序容器技术如何助力 App 快速打入全球市场?
  • LeetCode 1616.分割两个字符串得到回文串
  • PHP性能优化与高并发处理:从基础到高级实践
  • 直播间里的酒旅新故事:内容正在重构消费链路
  • 设计模式:状态模式 State
  • 配置daemon.json使得 Docker 容器能够使用服务器GPU【验证成功】
  • 设计模式十三:代理模式(Proxy Pattern)
  • mac 字体遍历demo
  • 网络原理 - TCP/IP(一)