【QQmusic】复习笔记第四章分点讲解
4.1 音乐加载
功能概述
该部分实现了从本地磁盘加载音乐文件到程序中,并在界面上显示的功能。通过QFileDialog
类创建文件选择对话框,用户可选择多个音乐文件,程序筛选出有效音频文件后,交由MusicList
类管理,并更新到本地音乐页面显示。
核心实现步骤
1. 使用QFileDialog创建文件对话框
通过QFileDialog
类实现文件选择功能,设置对话框的标题、打开模式、文件筛选条件等:
QFileDialog fileDialog(this);
fileDialog.setWindowTitle("添加本地音乐"); // 设置对话框标题
fileDialog.setAcceptMode(QFileDialog::AcceptOpen); // 设置为打开文件模式
fileDialog.setFileMode(QFileDialog::ExistingFiles); // 允许选择多个现有文件
2. 筛选音频文件(MIME类型过滤)
使用QMimeDatabase
检测文件类型,仅加载支持的音频格式(如MP3、FLAC):
QStringList mimeList;
mimeList << "audio/mpeg" << "audio/flac"; // 支持的MIME类型
fileDialog.setMimeTypeFilters(mimeList); // 设置文件过滤器
3. 设置默认打开目录
指定对话框默认打开的目录,方便用户快速找到音乐文件:
QDir dir(QDir::currentPath());
dir.cdUp(); // 切换到上一级目录
QString musicPath = dir.path() + "/QQMusic/musics/";
fileDialog.setDirectory(musicPath); // 设置默认目录
4. 处理用户选择的文件
用户点击“打开”后,获取选中的文件路径列表,切换到本地音乐页面,并将文件交由MusicList
类解析和管理:
if (fileDialog.exec() == QFileDialog::Accepted) {ui->stackedWidget->setCurrentIndex(4); // 切换到本地音乐页面(索引4)QList<QUrl> urls = fileDialog.selectedUrls(); // 获取选中的文件URLmusicList.addMusicByUrl(urls); // 交由MusicList处理ui->localPage->reFresh(musicList); // 更新本地音乐列表显示
}
关键类与方法
QFileDialog类
- 作用:创建文件选择对话框,支持用户选择单个或多个文件。
- 核心方法:
setAcceptMode()
:设置对话框模式(打开/保存)。setFileMode()
:设置文件选择模式(单个文件、多个文件、目录等)。setMimeTypeFilters()
:通过MIME类型过滤文件,确保仅显示音频文件。selectedUrls()
:获取用户选中的文件URL列表。
QMimeDatabase类
- 作用:检测文件的MIME类型,验证是否为音频文件。
- 核心方法:
mimeTypeForFile()
:获取文件的MIME类型,用于过滤无效文件(如非音频文件)。
代码逻辑详解
void QQMusic::on_addLocal_clicked() {QFileDialog fileDialog(this);fileDialog.setWindowTitle("添加本地音乐");fileDialog.setAcceptMode(QFileDialog::AcceptOpen);fileDialog.setFileMode(QFileDialog::ExistingFiles);// 设置MIME过滤器,仅显示MP3和FLAC文件QStringList mimeList;mimeList << "audio/mpeg" << "audio/flac";fileDialog.setMimeTypeFilters(mimeList);// 设置默认目录QDir dir(QDir::currentPath());dir.cdUp();QString musicPath = dir.path() + "/QQMusic/musics/";fileDialog.setDirectory(musicPath);if (fileDialog.exec() == QFileDialog::Accepted) {// 切换到本地音乐页面ui->stackedWidget->setCurrentIndex(4);// 获取选中的文件URLQList<QUrl> urls = fileDialog.selectedUrls();// 将文件添加到MusicList中musicList.addMusicByUrl(urls);// 更新本地音乐页面显示ui->localPage->reFresh(musicList);}
}
功能扩展点
- 支持更多音频格式:在MIME过滤器中添加更多支持的类型(如
audio/wav
)。 - 进度提示:在加载大量文件时显示进度条,提升用户体验。
- 重复文件检测:通过文件路径或MD5校验避免重复加载同一文件。
通过以上步骤,实现了本地音乐文件的加载、筛选和界面显示,为后续的播放、收藏、历史记录等功能奠定了数据基础。
4.2 MusicList类详解
一、类的定义与核心作用
MusicList类
是项目中管理音乐列表的核心数据结构,主要负责以下功能:
- 统一管理音乐对象:存储所有加载的音乐文件(
Music
实例),支持添加、查找、筛选等操作。 - 格式筛选与唯一性保证:过滤无效文件格式,避免重复加载相同音乐。
- 与数据库交互:实现音乐信息的持久化存储与读取(后续结合数据库模块)。
二、核心成员变量
成员变量 | 类型 | 说明 |
---|---|---|
musicList | QVector<Music> | 存储所有音乐对象,利用QVector 的顺序存储和快速访问特性。 |
musicPaths | QSet<QString> | 记录已加载音乐的文件路径,避免重复添加同一文件(基于路径唯一性)。 |
三、核心功能实现
1. 音乐文件加载与格式筛选
- 功能:从文件路径列表中筛选有效音频文件(MP3/FLAC),创建
Music
对象并添加到列表。 - 实现步骤:
- 遍历文件路径:通过
addMusicByUrl
方法接收QList<QUrl>
类型的文件路径。 - MIME类型检测:使用
QMimeDatabase
检测文件类型,仅保留audio/mpeg
(MP3)和audio/flac
(FLAC)格式。QMimeDatabase db; QMimeType mime = db.mimeTypeForFile(musicUrl.toLocalFile()); if (mime.name() != "audio/mpeg" && mime.name() != "audio/flac") continue;
- 唯一性检查:通过
musicPaths
集合判断文件是否已加载,避免重复添加。if (musicPaths.contains(musicPath)) continue; musicPaths.insert(musicPath);
- 创建Music对象:为有效文件创建
Music
实例,自动解析元数据(名称、歌手、专辑等)。
- 遍历文件路径:通过
2. 高效查找与遍历支持
- 通过
musicId
查找音乐:未来可添加findMusicById
方法(文档中后续扩展),通过遍历musicList
匹配唯一ID,确保快速定位音乐对象。 - 范围遍历支持:重载
begin()
和end()
方法,支持范围for
循环遍历,方便与界面模块(如CommonPage
)交互。iterator begin() { return musicList.begin(); } iterator end() { return musicList.end(); }
3. 数据持久化准备(后续扩展)
- 数据库表映射:后续可通过
MusicList
将音乐信息写入数据库(如musicInfo
表),包含musicId
、名称、歌手、路径、收藏状态等字段。 - 批量操作:提供
writeToDB()
和readFromDB()
方法,实现程序退出时保存音乐列表、启动时恢复数据(见文档6.3节数据库部分)。
四、关键代码示例
// MusicList.h 核心声明
class MusicList {
public: void addMusicByUrl(const QList<QUrl>& urls); // 加载音乐文件 iterator begin(); iterator end(); // 支持范围遍历
private: QVector<Music> musicList; // 存储音乐对象 QSet<QString> musicPaths; // 已加载文件路径集合(避免重复)
}; // MusicList.cpp 添加音乐逻辑
void MusicList::addMusicByUrl(const QList<QUrl>& urls) { for (const auto& url : urls) { QString musicPath = url.toLocalFile(); if (musicPaths.contains(musicPath)) continue; // 跳过已加载文件 QMimeDatabase db; QMimeType mime = db.mimeTypeForFile(musicPath); if (mime.name() != "audio/mpeg" && mime.name() != "audio/flac") continue; // 筛选有效格式 Music music(url); // 创建Music对象,自动解析元数据 musicList.push_back(music); musicPaths.insert(musicPath); // 记录路径 }
}
五、与其他模块的协作
- 与
Music类
协作:- 每个音乐文件对应一个
Music
对象,MusicList
存储这些对象,依赖Music
类解析元数据(如parseMediaMetaData
方法)和标记状态(isLike
、isHistory
)。
- 每个音乐文件对应一个
- 与界面交互:
CommonPage
页面(如“本地下载”)通过MusicList
筛选对应条件的歌曲(如未被收藏的本地文件),更新界面显示。
- 与数据库交互:
- 程序启动时通过
readFromDB()
从数据库加载历史数据,退出时通过writeToDB()
保存当前状态,确保数据持久化。
- 程序启动时通过
六、设计优势
- 格式兼容性:通过MIME类型检测,支持多种音频格式扩展(可新增支持
audio/wav
等)。 - 性能优化:使用
QSet
实现O(1)时间复杂度的重复文件检测,避免冗余加载。 - 代码复用:统一管理音乐数据,为“我喜欢”“最近播放”等功能提供底层数据支持,减少重复逻辑。
通过MusicList类
,项目实现了对音乐文件的高效管理、格式筛选和状态维护,为后续播放控制、界面显示和数据持久化奠定了基础。
4.3 Music类解析
一、类的定义与核心作用
Music类
是项目中描述单个音乐文件的核心数据模型,负责封装音乐的元数据(如名称、歌手、专辑等)、状态信息(收藏、历史播放)及文件路径,是音乐管理、播放控制和数据持久化的基础。具体作用包括:
- 数据封装:统一管理音乐文件的基本信息和状态,便于界面显示和逻辑处理。
- 元数据解析:自动提取音乐文件的元数据(标题、作者等),处理缺失信息并设置默认值。
- 状态标记:支持标记音乐是否被收藏(
isLike
)或播放过(isHistory
),为“我喜欢”“最近播放”等功能提供数据支持。 - 唯一性保证:通过UUID生成唯一标识,避免重复添加同一首歌曲。
二、核心成员变量
成员变量 | 类型 | 说明 |
---|---|---|
isLike | bool | 标记音乐是否被收藏(默认false ),界面通过此值显示“小心心”图标。 |
isHistory | bool | 标记音乐是否被播放过(默认false ),用于“最近播放”页面筛选数据。 |
musicName | QString | 歌曲名称,解析自文件元数据或文件名,默认“歌曲未知”。 |
singerName | QString | 歌手名称,支持多歌手用逗号分隔,默认“歌手未知”。 |
albumName | QString | 专辑名称,默认“专辑名未知”。 |
duration | qint64 | 歌曲总时长(毫秒),用于播放进度和时长显示。 |
musicId | QString | 唯一标识(UUID生成),确保同一歌曲多次加载时视为同一对象,避免重复。 |
musicUrl | QUrl | 歌曲文件在磁盘中的路径,用于播放和数据库存储。 |
三、构造函数与初始化
-
默认构造函数
Music::Music() : isLike(false), isHistory(false) {}
- 初始化收藏和历史状态为未标记状态。
-
带路径的构造函数
Music::Music(const QUrl &url) : isLike(false), isHistory(false), musicUrl(url) { musicId = QUuid::createUuid().toString(); // 生成UUID保证唯一性 parseMediaMetaData(); // 解析元数据(标题、歌手、专辑、时长) }
- UUID生成:使用
QUuid::createUuid()
生成唯一ID(如550e8400-e29b-41d4-a716-446655440000
),避免重复添加相同歌曲。 - 元数据解析:调用
parseMediaMetaData()
提取文件元数据,处理缺失信息(如盗版歌曲设置默认值)。
- UUID生成:使用
四、元数据解析(核心功能)
通过QMediaPlayer
解析音乐文件的元数据,处理可能缺失的信息:
void Music::parseMediaMetaData() { QMediaPlayer player; player.setMedia(musicUrl); while (!player.isMetaDataAvailable()) { QCoreApplication::processEvents(); // 保持界面响应,避免卡死 } if (player.isMetaDataAvailable()) { musicName = player.metaData("Title").toString().trimmed(); singerName = player.metaData("Author").toStringList().join(",").trimmed(); albumName = player.metaData("AlbumTitle").toString().trimmed(); duration = player.duration(); } // 处理空值情况 if (musicName.isEmpty()) musicName = "歌曲未知"; if (singerName.isEmpty()) singerName = "歌手未知"; if (albumName.isEmpty()) albumName = "专辑名未知";
}
- 处理逻辑:若元数据缺失(如无标题),设置默认值(如“歌曲未知”)。
- 线程安全:通过
QCoreApplication::processEvents()
处理事件循环,确保解析时界面可交互。
五、唯一性与状态管理
-
唯一性保证
- 使用UUID作为
musicId
,通过QUuid::createUuid()
生成全局唯一标识,避免同一文件多次加载时创建重复对象。 - 在
MusicList
类中通过musicMap
哈希表(键为musicId
,值为索引)实现O(1)时间复杂度的快速查找。
- 使用UUID作为
-
状态标记
setIsLike(bool)
和setIsHistory(bool)
方法更新收藏和历史状态,界面(如ListItemBox
)通过getIsLike()
和getIsHistory()
获取状态并显示对应图标(如红色小心心表示已收藏)。
六、与其他模块的交互
-
数据库持久化
insertMusicToDB()
:将音乐信息写入数据库(见6.3.2节),包括musicId
、名称、歌手、路径、状态等字段。MusicList
类通过readFromDB()
从数据库加载歌曲时,创建Music
对象并填充数据。
-
界面显示
CommonPage
页面(如“我喜欢”)通过Music
的get
方法获取歌曲名称、歌手、专辑等信息,填充到ListItemBox
中显示。- 收藏功能:点击“小心心”时,调用
setIsLike(true)
标记歌曲,并更新数据库和界面。
-
播放控制
- 提供
musicUrl
给QMediaPlayer
加载音频文件,支持播放、暂停、进度调节等操作。
- 提供
七、关键代码示例
// 生成唯一UUID
musicId = QUuid::createUuid().toString(); // 解析元数据并处理空值
if (player.metaData("Title").toString().isEmpty()) { musicName = "歌曲未知";
} // 状态标记
void setIsLike(bool isLike) { this->isLike = isLike; }
bool getIsLike() { return isLike; }
八、总结
Music类
是项目的核心数据载体,实现了以下核心功能:
- 数据封装:统一管理歌曲元数据和状态,确保信息一致性。
- 唯一性:通过UUID避免重复加载,提升数据管理效率。
- 元数据处理:自动解析文件信息,处理异常情况,保证界面正确显示。
- 持久化支持:与数据库交互,实现歌曲信息的保存和恢复。
该类的设计为“我喜欢”“最近播放”等功能提供了底层数据支持,是音乐管理、播放控制和界面显示的基础。
4.4 音乐分类
一、功能概述
QQMusic通过CommonPage
类实现“我喜欢”“本地下载”“最近播放”三个页面的音乐分类显示。核心逻辑是通过枚举类型区分页面类型,结合音乐对象的状态标记(如是否收藏、是否播放过)进行数据过滤,并在界面上动态更新对应列表。
二、页面类型枚举定义
在CommonPage
类中定义枚举PageType
,明确区分三种页面类型,确保每个页面知道自己需要显示的音乐类型:
enum PageType { LIKE_PAGE, // 我喜欢页面 LOCAL_PAGE, // 本地下载页面 HISTORY_PAGE // 最近播放页面
};
- 作用:通过枚举值(如
LIKE_PAGE
)标记当前页面类型,后续根据类型过滤音乐数据。
三、核心成员变量
成员变量 | 类型 | 说明 |
---|---|---|
pageType | PageType | 标记当前页面属于哪种类型(如LIKE_PAGE ),决定数据过滤逻辑。 |
musicListOfPage | QVector<QString> | 存储当前页面的音乐ID列表(仅保存musicId ,而非完整对象,节省内存)。 |
四、初始化与类型设置
在QQMusic
的initUi()
方法中,为三个页面设置类型和初始UI:
ui->likePage->setMusicListType(PageType::LIKE_PAGE);
ui->likePage->setCommonPageUI("我喜欢", ":/images/ilikebg.png");
ui->localPage->setMusicListType(PageType::LOCAL_PAGE);
ui->localPage->setCommonPageUI("本地音乐", ":/images/localbg.png");
ui->recentPage->setMusicListType(PageType::HISTORY_PAGE);
ui->recentPage->setCommonPageUI("最近播放", ":/images/recentbg.png");
setMusicListType
:设置页面类型,触发后续数据过滤逻辑。setCommonPageUI
:设置页面标题和背景图片,统一页面风格。
五、音乐数据过滤逻辑
在CommonPage::addMusicToMusicPage
方法中,根据pageType
过滤MusicList
中的音乐:
void CommonPage::addMusicToMusicPage(MusicList &musicList) { musicListOfPage.clear(); // 清空旧数据,避免重复 for (auto& music : musicList) { switch (pageType) { case LOCAL_PAGE: // 本地页面直接添加所有音乐(无过滤,显示所有本地加载的音乐) musicListOfPage.push_back(music.getMusicId()); break; case LIKE_PAGE: // 喜欢页面仅添加标记为“喜欢”的音乐 if (music.getIsLike()) { musicListOfPage.push_back(music.getMusicId()); } break; case HISTORY_PAGE: // 历史页面仅添加标记为“已播放”的音乐 if (music.getIsHistory()) { musicListOfPage.push_back(music.getMusicId()); } break; } }
}
- 过滤逻辑:
- 本地下载:直接添加所有本地加载的音乐(无过滤)。
- 我喜欢:仅添加
isLike
为true
的音乐。 - 最近播放:仅添加
isHistory
为true
的音乐。
六、界面数据更新
在CommonPage::reFresh
方法中,根据过滤后的musicListOfPage
更新界面显示:
- 遍历音乐ID:通过
musicId
从MusicList
中查找对应的Music
对象。 - 创建列表项:为每个音乐创建
ListItemBox
,设置歌曲名称、歌手、专辑和收藏状态(小心心图标)。
for (auto musicId : musicListOfPage) { auto it = musicList.findMusicById(musicId); if (it != musicList.end()) { ListItemBox* item = new ListItemBox(ui->pageMusicList); item->setMusicName(it->getMusicName()); item->setSinger(it->getSingerName()); item->setAlbumName(it->getAlbumName()); item->setLikeIcon(it->getIsLike()); // 设置收藏状态图标 // 添加到QListWidget QListWidgetItem* listItem = new QListWidgetItem(ui->pageMusicList); listItem->setSizeHint(QSize(ui->pageMusicList->width(), 45)); ui->pageMusicList->setItemWidget(listItem, item); }
}
七、信号与槽关联
通过信号槽机制,当用户点击“播放全部”或双击歌曲时,通知QQMusic
类更新播放列表:
- 播放全部按钮:
// CommonPage中播放全部按钮的信号发射
connect(ui->playAllBtn, &QPushButton::clicked, this, [=]() { emit playAll(pageType); // 发射当前页面类型,告知QQMusic播放对应页面的音乐
});
- QQMusic处理逻辑:
// QQMusic中处理播放全部的槽函数
void QQMusic::onPlayAll(PageType pageType) { CommonPage* page = getPageByType(pageType); // 根据类型获取对应页面 page->addMusicToPlayer(musicList, playList); // 将页面音乐添加到播放列表 player->play(); // 开始播放
}
八、核心优势
- 代码复用:
- 通过
CommonPage
统一管理三个页面的布局和逻辑,仅通过pageType
区分功能,减少重复代码(如列表显示、按钮交互)。
- 通过
- 数据隔离:
- 每个页面仅存储对应音乐的
musicId
,通过唯一ID关联完整Music
对象,高效且节省内存。
- 每个页面仅存储对应音乐的
- 灵活过滤:
- 利用
Music
类的isLike
和isHistory
属性,轻松实现不同页面的筛选(如仅显示收藏或历史播放的音乐)。
- 利用
- 界面统一:
- 使用自定义控件
ListItemBox
统一显示格式,确保三个页面的视觉和交互一致,提升用户体验。
- 使用自定义控件
九、总结
音乐分类功能通过枚举标记页面类型,结合数据过滤和界面更新逻辑,实现了“我喜欢”“本地下载”“最近播放”的高效管理。核心在于通过CommonPage
复用代码,利用状态标记筛选数据,确保不同页面快速展示对应内容,同时通过信号槽机制与播放模块联动,提升整体功能的一致性和可维护性。
相关文章:
【QQmusic】复习笔记第四章分点讲解
4.1 音乐加载 功能概述 该部分实现了从本地磁盘加载音乐文件到程序中,并在界面上显示的功能。通过QFileDialog类创建文件选择对话框,用户可选择多个音乐文件,程序筛选出有效音频文件后,交由MusicList类管理,并更新到…...
设置右键打开VSCode
在日常的开发工作中,VSCode 是一款非常受欢迎的代码编辑器。为了更加便捷地使用它,我们可以将 VSCode 添加到右键菜单中,这样只需右键点击文件或文件夹,就能快速用 VSCode 打开,极大地提高工作效率。下面我就来介绍一下…...
数据结构和算法(八)--2-3查找树
目录 一、平衡树 1、2-3查找树 1.1、定义 1.2、查找 1.3、插入 1.3.1、向2-结点中插入新键 1.3.2、向一棵只含有一个3-结点的树中插入新键 1.3.3、向一个父结点为2-结点的3-结点中插入新键 1.3.4、向一个父结点为3-结点的3-结点中插入新键 1.3.5、分解根结点 1.4、2…...
JSAPI2.4——正则表达式
一、语法 const str 一二三四五六七八九十 //判断内容 const reg /二/ //判断条件 console.log(reg.test(str)); //检查 二、test与exec方法的区别 test方法:用于判断是否符合规则的字符串,返回值是布尔值 exec方法&…...
FPGA 100G UDP纯逻辑协议栈
随着器件等级的升高,高速serdes的线速率也随之提高,RFSOC 4x最大可支持100G,主流方案为RDMA方案,该方案相对比较复杂,除了需要负责逻辑端的开发,还需操作系统中开发RDMA的驱动,对于对丢包不那么…...
分享一个可以批量巡检GET和POST接口的Shell脚本
一、场景痛点与需求分析 在分布式系统架构中,服务接口的可用性和稳定性直接影响业务连续性。当面临以下场景时,需批量巡检GET和POST接口: 上线验证:新版本发布后批量验证核心接口 故障恢复:异常数据修复后的批量重试…...
机器学习之一:机械式学习
正如人们有各种各样的学习方法一样,机器学习也有多种学习方法。若按学习时所用的方法进行分类,则机器学习可分为机械式学习、指导式学习、示例学习、类比学习、解释学习等。这是温斯顿在1977年提出的一种分类方法。 有关机器学习的基本概念,…...
区分PROJECT_SOURCE_DIR, CMAKE_SOURCE_DIR,CMAKE_CURRENT_SOURCE_DIR
目录 示例工程 PROJECT_SOURCE_DIR的行为 CMAKE_SOURCE_DIR的行为 CMAKE_CURRENT_SOURCE_DIR 示例工程 根目录 |-----CMakeLists.txt |-----sub1 |--------CMakeLists.txt |-----sub2 |--------CMakeLists.txt 根目录下的CMakeList.txt: project(main)message("main …...
Python循环结构深度解析与高效应用实践
引言:循环结构在编程中的核心地位 循环结构作为程序设计的三大基本结构之一,在Python中通过while和for-in两种循环机制实现迭代操作。本文将从底层原理到高级应用,全面剖析Python循环机制的使用技巧与优化策略,助您掌握高效迭代的…...
25【干货】在Arcgis中根据字段属性重新排序并自动编号的方法(二)
上一篇关于属性表自动编号的文章因为涉及到代码(【干货】在Arcgis中根据字段属性重新排序并自动编号的方法(一)),担心大家有些东西确实不熟悉,今天就更新一篇不需要代码也能达到这个目的的方法。主要的思路…...
SinSR模型剪枝实验报告
SinSR模型剪枝实验报告 实验概述 我成功地对SinSR模型进行了L1范式剪枝,剪枝比例为50%。通过分析剪枝前后的模型参数和性能,我们得出了以下结论。 剪枝实现方法 创建专用的main_prune.py脚本,用于剪枝训练。创建quick_prune.py脚本&#…...
IT社团分析预测项目(pandas、numpy、sklearn)
IT社团人数的增长陷入迟滞,同时不同目标任务和不同经营模式的社团更是层出不穷。在面临内忧外患的情况下,本社团希望结合社团行业现状,分析同学和出勤的数据,挖据数据中的信息,通过对人数流失进行预测寻找到相应的对策…...
C语言中位段的应用
一,位段的主要应用场景 硬件寄存器操作 嵌入式开发中,硬件寄存器通常以位为单位控制设备状态。位段可直接映射到寄存器,简化位操作: typedef struct {unsigned int enable : 1; // 使能位unsigned int mode : 3; // 模式选择&…...
【Linux网络#1】:网络基础知识
1、网络发展 在计算机发展历程中,经历过下面四个阶段: 1.独立模式 独立模式:计算机之间相互独立,每台计算机做自己的事情,彼此之间没有直接信息传递。如果两台计算机需要通信就需要将当前计算机的数据通过某种方式拷贝…...
基于物联网的园林防火监测系统
标题:基于物联网的园林防火监测系统 内容:1.摘要 随着全球气候变化和人类活动影响,园林火灾发生频率呈上升趋势,给生态环境和人类生命财产造成巨大损失。为有效预防和应对园林火灾,本文提出基于物联网的园林防火监测系统。该系统综合运用传感…...
华为云loT物联网介绍与使用
🌐 华为云 IoT 物联网平台详解:构建万物互联的智能底座 随着万物互联时代的到来,物联网(IoT)已成为推动数字化转型的关键技术之一。华为云 IoT 平台(IoT Device Access)作为华为云的核心服务之…...
Redis 数据类型全览:特性、场景与操作实例
Redis 是一款开源的内存数据库,支持多种数据类型,以下是对常见 Redis 数据类型的介绍: 1. String(字符串) 描述 字符串是 Redis 里最基础的数据类型,其值可以是简单的字符串、数字,甚至是二进…...
Qt动态库信号崩溃问题解决方案
在Qt中,当动态库向主程序发送信号导致崩溃时,通常涉及线程安全或对象生命周期问题。以下是逐步解决方案: 1. 检查线程上下文 问题:动态库所在的线程与主程序线程不同,跨线程信号未正确处理。解决方案: 显式…...
Go设计模式-观察者模式
简介 在软件开发中,我们常常会遇到这样的场景:一个对象的状态变化需要通知到多个其他对象,让它们做出相应的反应。观察者模式(Observer Pattern)就是解决这类问题的一种设计模式。在 Go 语言中,由于其简洁…...
《TCP/IP详解 卷1:协议》之第七、八章:Ping Traceroute
目录 一、ICMP回显请求和回显应答 1、ICMP回显请求 2、ICMP回显应答 二、ARP高速缓存 三、IP记录路由选项(Record Route,RR) 1、记录路由选项的工作过程 2、RR 选项的 IP 头部格式 2.1、RR 请求 2.2、RR响应 四、ping 的去返路径 五…...
Unity任务系统笔记
数据结构设计 任务基类包括的字段: string 任务内容; Transform 任务目的地; MyCharacter 任务开启后要更新对话的NPC; MyTalkData 任务开启后相关NPC要说的对话数据; 共同方法:开启任务、完成任务。…...
Three.js + React 实战系列-3D 个人主页:构建 Hero 场景组件(项目核心)✨
在本节中,我们将完成整个 3D 主业项目中最核心的组件 —— Hero.jsx。 这个组件作为首页的主视觉部分,整合了 3D 模型、动画相机、交互按钮与自适应布局,构建出一个立体、酷炫、可交互的主场景。 前置准备: ✅安装依赖ÿ…...
线程池(二):深入剖析synchronized关键字的底层原理
线程池(二):深入剖析synchronized关键字的底层原理 线程池(二):深入剖析synchronized关键字的底层原理一、基本使用1.1 修饰实例方法1.2 修饰静态方法1.3 修饰代码块 二、Monitor2.1 Monitor的概念2.2 Moni…...
网络原理 - 9
目录 数据链路层 以太网 以太网帧格式 MAC 地址 DNS(Domain Name System) 完! 数据链路层 这里的内容也是简单了解,除非是做交换机开发,一般程序员不需要涉及~~ 以太网 ”以太网“不是一种具体的网络…...
springboot入门-业务逻辑核心service层
在 Spring Boot 中,Service 层是业务逻辑的核心,负责协调数据访问层(Repository 或 Mapper)和控制器层(Controller),处理业务规则、事务管理以及数据转换。以下是 Service 层的详细说明、常用注…...
在RHEL 10上安装和配置TFTP服务器(不使用xinetd)
RHEL10已经废弃xinetd,使用下面的方式安装配置TFTP服务器。 1. 安装TFTP服务器和客户端 sudo dnf install tftp-server tftp -y 2. 配置TFTP服务器 创建TFTP根目录并设置权限 sudo mkdir -p /var/lib/tftpboot sudo chmod -R 777 /var/lib/tftpboot sudo chown -R…...
AIGC在游戏开发中的革命:自动化生成3A级游戏内容
一、智能游戏开发架构 1.1 传统开发痛点与AIGC创新 开发环节 传统痛点 AIGC解决方案 角色原画设计 美术资源产能瓶颈 文生图3D模型自动生成 场景搭建 重复劳动占比高 程序化生成风格迁移 NPC行为设计 模式化严重 强化学习驱动智能行为 任务系统 剧情线性缺乏变化 动态剧情生成系…...
ChatGPT、deepseek、豆包、Kimi、通义千问、腾讯元宝、文心一言、智谱清言代码能力对比
均使用测试时的最强模型 均是一次对话,对话内容一样 均开启深度思考 能联网的都联网了,但是作用不大,因为蓝桥杯刚考完,洛谷题目刚上传没多久 问题一测试了两遍 从问题三开始不再测试智谱清言(它思考时间太长了,前两个…...
Linux扩展
目录 扩展 查找如何进行后台运行程序的指令 使用 & 符号 使用 nohup 命令 使用 screen 或 tmux find命令 基本语法 常用选项 grep 命令 基本语法 常用选项 如何使用 vim 直接定位到错误行 1. 使用 :make 和 :copen 2. 使用 :lineno 定位 3. 通过 :grep 或 :…...
Java Hotspot VM researcher
** therefore, careful design and understanding of modules are essential to fully reap the performance benefits. **...
java—基础
目标 ├── 第一阶段:内容清单 │ └── 目标:建立编程思想 ├── 第二阶段:内容清单 │ └── 目标:提升编程能力 └── 第三阶段:内容清单└── 目标:分析需求,代码实现能力以下是根…...
【OpenCV】第二章——图像处理基础
图像处理基础学习笔记 本章节详细介绍了图像处理的基础内容,包括图像的读取、显示、保存,基本属性的查看,图像的变换与操作,以及常用的图像处理方法。 目录 图像的读取与显示图像基本属性图像的灰度化与二值化图像的色彩空间转换…...
在WSL2+Ubuntu22.04中通过conda pack导出一个conda环境包,然后尝试导入该环境包
如何导出一个离线conda环境?有两种方式,一种是导出env.yml即环境配置,一种是通过conda pack导出为一个环境包,前者只是导出配置(包括包名、版本等),而后者是直接将环境中所有的内容打包…...
C++:类和对象(上)---镜中万象:C++类的抽象之境与对象的具体之象
类(Class)是一种用户自定义的数据类型。 文章目录: 前言一、面向过程和面向对象初步认识 二、类的引入 三、类的定义 3.1类是什么? 3.2类的定义 四、类的访问限定符和封装 4.1类的访问限定符 4.2封装 五、类和对象的关系 六、类对…...
碰一碰发视频源码搭建全解析,支持OEM
在数字化交互体验不断升级的背景下,“碰一碰发视频” 功能凭借其便捷性和趣味性,逐渐成为营销推广、社交分享等场景中的热门需求。该功能基于近场通信技术,实现设备间快速的数据传输。本文将详细介绍其源码搭建过程,助力开发者实现…...
搭建spark-local模式
要搭建Spark的local模式,你可以按照以下步骤进行操作(以在Linux系统上安装为例,假设你已经安装了Java环境): 1. 下载Spark安装包:访问Spark官方网站(https://spark.apache.org/downloads.html&a…...
Goland终端PowerShell命令失效
Goland终端Terminal的PowerShell不能使用,明明windows上升级了PowerShell 7设置了配置文件,但是只能在windows终端下使用,goland终端下直接失效报错,安装升级PowerShell请看[博客](Windows11终端升级PowerShell7 - HashFlag - 博客…...
前端节流、防抖函数
节流 什么是节流? 节流就是同一个事件 一秒钟他执行了很多次。但是我不想他执行这么多次,我只想让他执行一次 或者两次。 那该怎么办? why baby why 那我想就是他执行的时候 我就设置一个定时器,如果定时器是空的,等会…...
如何使用WebRTC
WebRTC比较容易使用,只需要很少的步骤,有些消息在浏览器和服务器之间流动,有些则直接在两个浏览器之间流动, 1、建立WebRTC会话 a:建立WebRTC连接需要加入以下几个步骤: 获取本地媒体:getUse…...
在 Vue 3 setup() 函数中使用 TypeScript 处理 null 和 undefined 的最佳实践
在 Vue 3 中使用 setup() 函数和 TypeScript 时,null 和 undefined 是两个需要特别关注的类型。虽然它们看起来都表示“没有值”,但它们在 JavaScript 和 TypeScript 中有着不同的含义和使用场景。如果不小心处理它们,可能会导致潜在的 bug 或…...
【C++11】Lambda表达式
前言 上文我们学习了C11新语法,可变参数模板以及用可变参数模板作为形参的emplace接口。【C11】可变参数模板-CSDN博客 本文我们来学习C11下一个新语法,Lambda表达式。 1.Lambda表达式语法 Lambda表达式本质是一个匿名函数对象,与普通函数不同…...
【落羽的落羽 C++】vector
文章目录 一、vector类介绍二、vector中的常用接口三、迭代器失效问题四、vector的使用实例五、vector模拟实现 一、vector类介绍 vector是STL中的一种容器,本质上是顺序表。它和string类的结构很相似,其也有size、capacity、数组等,不同的是…...
DIFY 浅尝 - Dify + Ollama 抓取BBC新闻
假设你已经按照上篇文章 DIFY 浅尝 - DIFY Ollama 添加模型搭建好了本地环境. 创建一个新的工作流 进入你的本地Dify工作台,选择工作室->创建空白应用 选择工作流,输入应用名称BBC旅游新闻,点击创建 创建一个网页爬虫 配置网页爬虫…...
基于MTF的1D-2D-CNN-BiLSTM-Attention时序图像多模态融合的故障分类识别(Matlab完整源码和数据),适合研究学习,附模型研究报告
基于MTF的1D-2D-CNN-BiLSTM-Attention时序图像多模态融合的故障分类识别(Matlab完整源码和数据),适合研究学习,附模型研究报告 目录 基于MTF的1D-2D-CNN-BiLSTM-Attention时序图像多模态融合的故障分类识别(Matlab完整…...
nuxt3项目搭建:一、初始化项目流程指南
一、初始化项目 初始化命令 1、创建nuxt3项目 npm create nuxtlatest2、填写项目名称 这里我直接填了nuxt-app 3、选择包管理器 这里的包管理器我们选择pnpm 4、选择是否创建git仓库 选择完包管理器后,脚手架会自动下载依赖,git仓库我已经创建好了…...
案例速成GO+redis 个人笔记
更多个人笔记:(仅供参考,非盈利) gitee: https://gitee.com/harryhack/it_note github: https://github.com/ZHLOVEYY/IT_note (更多GOredis等见内部,会及时更新~&#x…...
C/C++ 头文件包含机制:从语法到最佳实践
在C/C++编程中,头文件(.h 或 .hpp)扮演着至关重要的角色。它们不仅是代码模块化的基石,更是编译器理解程序结构的关键。然而,头文件的使用看似简单,实则暗含许多细节,稍有不慎便可能导致编译错误、代码冗余,甚至隐藏难以调试的问题。本文将从语法、编译器行为到工程实践…...
职业教育新形态数字教材的建设与应用:重构教育生态的数字化革命
教育部新时代职业学校名师(名匠)名校长培养计划、四川省第四批职业学校名师(名匠)培养计划专题 在某职业院校的智能制造课堂上,学生佩戴VR设备,通过数字教材中的虚拟工厂完成设备装配训练,系统实时生成操作评分与改进建议。这一场景折射出职业…...
跟着deepseek学golang--Go vs Java vs JavaScript三语言的差异
文章目录 一、类型系统与编译方式1. 类型检查时机2. 空值安全设计 二、并发模型对比1. 并发单元实现4. 锁机制差异 三、内存管理机制1. 垃圾回收对比2. 对象模型差异 四、工程实践差异1. 依赖管理工具4. 异常处理范式 五、跨平台能力对比1. 编译输出目标 综合对比表五角星说…...
梯度下降法
梯度下降法是一种常见的求最小值(或最值)的方法。它是通过沿着函数梯度的负方向进行迭代更新,直到找到局部最小值或最大值。梯度下降法应用于多元函数时,通过更新参数的方式找到最优解。 梯度下降法步骤: 初始化参数&…...