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

【QQmusic自定义控件实现音乐播放器核心交互逻辑】第三章

🌹 作者: 云小逸
🤟 个人主页: 云小逸的主页
🤟 motto: 要敢于一个人默默的面对自己,强大自己才是核心。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前,其次就是现在!学会自己和解,与过去和解,努力爱自己。希望春天来之前,我们一起面朝大海,春暖花开!

🥇 专栏:

  • 动态规划
  • C 语言
  • C++
  • Java 语言
  • Linux 编程
  • 算法
  • 待续…

文章目录

    • 📚 前言
    • 一、BtForm
      • 1. BtForm界面设计
      • 2. BtForm类中实现
      • 3. 核心要点总结
    • 二、推荐页面
      • 1. 推荐页面分析
      • 2. 推荐页布局
      • 3. 自定义RecBox
      • 4. 自定义RecBoxItem
      • 5. RecBox添加RecBoxItem
      • 6. RecBox中btUp和btDown按钮clicked处理
      • 7. 核心要点总结
    • 三、自定义CommonPage
      • 1. CommonPage页面分析
      • 2. CommonPage页面布局
      • 3. CommonPage界面设置和显示
      • 4. 核心要点总结
    • 四、自定义ListItemBox
      • 1. ListItemBox页面分析
      • 2. ListItemBox页面布局
      • 3. ListItemBox显示测试
      • 4. 支持hover效果
      • 5. 核心要点总结
    • 五、自定义MusicSlider
      • 1. 功能与设计
      • 2. 交互实现
      • 3. 核心要点总结
    • 六、自定义VolumeTool
      • 1. 控件分析
      • 2. 界面布局
      • 3. 界面设置与交互
      • 4. 核心要点总结
    • 📣 结语

📚 前言

在Qt开发里,自定义控件是极为关键的,它能够帮助我们打造出交互性强且界面精美的应用程序。在QQMusic项目中,有几个重要的自定义控件,像BtForm、推荐页相关控件、CommonPage、ListItemBox、MusicSlider和VolumeTool等。下面我会详细解释这些控件的设计思路、实现方式以及关键代码,让你能更好地理解它们。


一、BtForm

1. BtForm界面设计

  • 功能定位:这个控件在音乐播放器的左侧,充当导航按钮。它不仅有图标和文本,还有动画效果。点击它能切换页面,同时会有跳动的竖条显示,提示你当前选中的是哪个按钮。
  • 界面组成
    • 整体控件大小是200*35 ,有个btStyle容器Widget。在这个容器里,btIcon用来显示图标,btText显示文本,lineBox是动画容器,里面有4个QLabel,这4个QLabel能实现跳动竖条的效果。
    • 界面采用水平布局,边距和间距都设为0。当鼠标放到按钮上时,背景色会变成#D8D8D8,让你知道鼠标移到这里了。
  • 提升操作:在bodyLeft里,把QWidget提升为BtForm自定义控件。这样就能通过属性来设置图标、文本和对应的页面ID,方便后续点击按钮切换页面。

2. BtForm类中实现

  • 数据设置
// btform.h
class BtForm : public QWidget {Q_OBJECT
public:int id = 0; // 按钮对应的页面IDvoid setIcon(QString btIcon, QString btText, int mid) {ui->btIcon->setPixmap(QPixmap(btIcon));ui->btText->setText(btText);this->id = mid;}
};

这段代码定义了BtForm类,setIcon方法用于设置按钮的图标、文本和对应的页面ID。具体来说,ui->btIcon->setPixmap(QPixmap(btIcon));把传入的图标路径对应的图片设置给btIconui->btText->setText(btText);把传入的文本设置给btTextthis->id = mid;则记录下这个按钮对应的页面ID,方便后续点击按钮时能准确切换到相应页面。

  • 点击响应
// btform.cpp
void BtForm::mousePressEvent(QMouseEvent *event) {Q_UNUSED(event);ui->btStyle->setStyleSheet("#btStyle{ background:rgb(30,206,154); color:#F6F6F6; }");emit click(id);
}

mousePressEvent方法是在鼠标点击按钮时触发。Q_UNUSED(event);是为了避免编译器警告,表示我们忽略这个事件参数。ui->btStyle->setStyleSheet("#btStyle{ background:rgb(30,206,154); color:#F6F6F6; }");把按钮的背景色设置为绿色,文本颜色设置为白色,让你能直观看到按钮被点击了。emit click(id);会发射一个点击信号,并且把按钮对应的页面ID传递出去,这样上层程序就能根据这个ID来切换页面。

  • 动画效果
// btform.cpp(构造函数)
BtForm::BtForm(QWidget *parent) : QWidget(parent) {QPropertyAnimation *animationLine1 = new QPropertyAnimation(ui->line1, "geometry", this);animationLine1->setDuration(1500);animationLine1->setKeyValueAt(0, QRect(0, 15, 2, 0));animationLine1->setKeyValueAt(0.5, QRect(0, 0, 2, 15));animationLine1->setKeyValueAt(1, QRect(0, 15, 2, 0));animationLine1->setLoopCount(-1);animationLine1->start();// 类似地为line2、line3、line4设置动画
}

在构造函数里,为line1创建了一个QPropertyAnimation对象。setDuration(1500);设置动画持续时间为1500毫秒。setKeyValueAt方法设置了动画的关键帧,在开始时(0时刻)竖条隐藏,到中间(0.5时刻)竖条完全显示,结束时(1时刻)竖条又隐藏。setLoopCount(-1);表示动画无限循环。这样,竖条就会一直跳动,增强了界面的动态感。对于line2line3line4也会做类似的动画设置。

  • 动画显示控制
// btform.cpp
void BtForm::showAnimal(bool isShow) {if (isShow) {ui->lineBox->show();} else {ui->lineBox->hide();}
}

showAnimal方法用来控制lineBox的显示或隐藏。如果传入的isShowtrue,就显示lineBox,也就是显示跳动的竖条;如果为false,就隐藏。默认情况下,本地下载按钮的动画是显示的。

3. 核心要点总结

  • 数据绑定:通过setIcon方法把图标、文本和页面ID关联起来,为按钮的功能实现奠定基础。
  • 点击交互:重写mousePressEvent方法处理点击事件,改变按钮外观并发射信号,实现页面切换的交互逻辑。
  • 动画增强:利用QPropertyAnimation实现竖条的动画效果,让界面更有活力。
  • 灵活控制:通过showAnimal方法能根据需要灵活控制动画的显示。

二、推荐页面

1. 推荐页面分析

  • 布局结构:推荐页面有“推荐”“今日为你推荐”“你的歌曲补给站”这些文本。中间是轮播图区域,能左右翻页,鼠标悬停在上面还有动画效果。
  • 核心组件
    • QScrollArea:它就像一个大容器,把所有推荐内容都装在里面,还支持滚动操作,方便你查看更多内容。
    • 自定义RecBox控件:里面有左右翻页按钮,还有推荐内容区域,负责管理推荐内容的显示和切换。
    • RecBoxItem控件:是单个的推荐项,鼠标放上去时,里面的图片会往上移动。

2. 推荐页布局

  • 层级结构
    • recPage页面添加了QScrollArea,它内部采用垂直布局。里面有标题标签,还有两个RecBox,分别对应“今日为你推荐”和“你的歌曲补给站”。
    • RecBox包含左右翻页按钮(btUp/btDown)和内容区域(recListUp/recListDown),采用水平布局。
  • 样式设置:翻页按钮的背景图是up_page.png/down_page.png,鼠标悬停在按钮上时,背景色会变成#1ECD97,有明显的交互反馈。

3. 自定义RecBox

  • 界面布局
    • 左右按钮宽度是30,内容区域分上下两行,每行能显示4个RecBoxItem
    • 通过initRecBoxUi方法接收数据和行数(1行或2行),动态生成推荐项。
// recbox.cpp
void RecBox::initRecBoxUi(const QJsonArray &data, int rows) {// 清空旧内容clearRecBox();// 根据行数和数据生成推荐项for (int i = 0; i < data.size(); ++i) {if (rows == 1) {// 处理一行的情况createRecBoxItem(data[i].toObject(), 0, i);} else {// 处理两行的情况int row = i / 4;int col = i % 4;createRecBoxItem(data[i].toObject(), row, col);}}
}

initRecBoxUi方法首先调用clearRecBox清空旧的推荐项,避免重复显示。然后根据传入的行数和数据来生成推荐项。如果是一行显示的情况,就直接调用createRecBoxItem添加到相应位置;如果是两行显示,就计算出每个推荐项所在的行和列,再调用createRecBoxItem添加。

  • 数据处理
    • 使用QJsonArray存储图片路径和文本,通过std::random_shuffle随机打乱顺序后分组显示,这样每次打开看到的推荐内容顺序都不一样。
    • createRecBoxItem方法根据行数和分组索引添加推荐项到上下布局。
// recbox.cpp
void RecBox::createRecBoxItem(const QJsonObject &obj, int row, int col) {RecBoxItem *item = new RecBoxItem(this);item->setItemData(obj["path"].toString(), obj["text"].toString());if (row == 0) {ui->recListUp->addWidget(item, 0, col);} else {ui->recListDown->addWidget(item, 0, col);}
}

createRecBoxItem方法创建一个RecBoxItem对象,调用setItemData方法设置图片路径和文本。然后根据行号判断是添加到上面的布局(recListUp)还是下面的布局(recListDown)。

4. 自定义RecBoxItem

  • 界面组成
    • musicImageBox:用来显示图片和点击按钮,鼠标放上去时会显示小手图标,提示你可以点击。
    • recBoxItemText:显示推荐文本,文本是居中对齐的。
  • 动画效果
// recboxitem.cpp
bool RecBoxItem::eventFilter(QObject *watched, QEvent *event) {if (watched == ui->musicImageBox) {int imgWidth = ui->musicImageBox->width();int imgHeight = ui->musicImageBox->height();if (event->type() == QEvent::Enter) {QPropertyAnimation *anim = new QPropertyAnimation(ui->musicImageBox, "geometry");anim->setDuration(100);anim->setStartValue(QRect(9, 10, imgWidth, imgHeight));anim->setEndValue(QRect(9, 0, imgWidth, imgHeight));anim->start();connect(anim, &QPropertyAnimation::finished, anim, &QObject::deleteLater);} else if (event->type() == QEvent::Leave) {QPropertyAnimation *anim = new QPropertyAnimation(ui->musicImageBox, "geometry");anim->setDuration(150);anim->setStartValue(QRect(9, 0, imgWidth, imgHeight));anim->setEndValue(QRect(9, 10, imgWidth, imgHeight));anim->start();connect(anim, &QPropertyAnimation::finished, anim, &QObject::deleteLater);}return true;}return QObject::eventFilter(watched, event);
}

eventFilter方法是个事件过滤器,用来拦截鼠标进入和离开musicImageBox的事件。当鼠标进入时,创建一个动画,让图片在100毫秒内从下移10px的位置移动到顶部;当鼠标离开时,创建另一个动画,让图片在150毫秒内从顶部移动回下移10px的位置。动画结束后,通过connect函数连接finished信号和deleteLater槽,释放动画对象的资源。

5. RecBox添加RecBoxItem

  • 数据准备
// qqmusic.cpp
QJsonArray QQMusic::randomPiction() {QVector<QString> imgNames;imgNames << "001.png" << "002.png" << ...;std::random_shuffle(imgNames.begin(), imgNames.end());QJsonArray objArray;for (int i = 0; i < imgNames.size(); ++i) {QJsonObject obj;obj.insert("path", ":/images/rec/" + imgNames[i]);obj.insert("text", QString("推荐-%1").arg(i, 3, 10, QChar('0')));objArray.append(obj);}return objArray;
}

randomPiction方法创建一个QVector存储图片名称,然后用std::random_shuffle打乱顺序。接着创建QJsonObject,把图片路径和推荐文本插入到对象中,再把对象添加到QJsonArray里。最后返回这个QJsonArray,这样就得到了随机顺序的推荐数据。

  • 分组逻辑
    • 上行RecBox(1行4列)和下行RecBox(2行4列)根据行数动态分配推荐项到上下布局。也就是说,根据不同的行数要求,把推荐项合理地放到对应的布局里显示。

6. RecBox中btUp和btDown按钮clicked处理

  • 翻页逻辑
// recbox.cpp
void RecBox::onBtUpClicked() {currentIndex = (currentIndex - 1 + groupCount) % groupCount;updateRecBox();
}void RecBox::onBtDownClicked() {currentIndex = (currentIndex + 1) % groupCount;updateRecBox();
}void RecBox::updateRecBox() {// 计算当前组的数据范围int start = currentIndex * 8;int end = qMin(start + 8, data.size());QJsonArray currentData;for (int i = start; i < end; ++i) {currentData.append(data[i]);}initRecBoxUi(currentData, currentIndex < groupCount - 1 ? 2 : 1);
}

onBtUpClicked方法在点击上一页按钮时调用,通过(currentIndex - 1 + groupCount) % groupCount计算新的索引,保证索引不会越界。onBtDownClicked方法在点击下一页按钮时调用,用(currentIndex + 1) % groupCount计算新索引。updateRecBox方法根据新索引计算当前组的数据范围,把这些数据添加到currentData中,然后调用initRecBoxUi方法更新显示内容。如果不是最后一组,就显示两行;如果是最后一组,就根据实际情况显示一行或两行。

  • 性能优化:更新前清除旧元素,避免重复添加,确保界面显示最新分组内容。这样可以提高界面的响应速度,避免出现显示混乱的问题。

7. 核心要点总结

  • 布局设计:采用分层布局和自定义控件组合,构建出推荐页的整体结构。
  • 数据处理:用QJsonArray存储和处理数据,随机打乱和分组显示增加了内容的多样性。
  • 交互体验:通过事件过滤器和QPropertyAnimation实现鼠标悬停动画,提升了用户的交互感受。
  • 性能保障:合理处理翻页逻辑和进行性能优化,保证了界面的流畅性和响应速度。

三、自定义CommonPage

1. CommonPage页面分析

  • 适用场景:适用于“我喜欢”“本地下载”“最近播放”等页面,这些页面布局相同,但显示的数据不同。
  • 界面结构
    • 标题QLabel:显示页面的标题,比如“本地音乐”。
    • musicPlayBox:里面有封面图和“播放全部”按钮。
    • listLabelBox:显示歌曲信息的标题,像名称、歌手、专辑等。
    • pageMusicList:使用QListWidget来显示歌曲列表。

2. CommonPage页面布局

  • 控件配置
    • 标题标签高度是30,封面图标签宽度是150,“播放全部”按钮尺寸是100*30,采用垂直弹簧布局,能自适应空间。
    • 列表标签采用水平布局,歌曲信息列对齐显示,让界面看起来更整齐。
  • 样式设置:按钮悬停时背景色变成#1ECD97,圆角为10px,增强了按钮的美观度和交互性。

3. CommonPage界面设置和显示

  • 初始化方法
// commonpage.cpp
void CommonPage::setCommonPageUI(const QString &title, const QString &image) {ui->pageTittle->setText(title);ui->musicImageLabel->setPixmap(QPixmap(image));ui->musicImageLabel->setScaledContents(true);
}

setCommonPageUI方法用于设置页面的标题和封面图。ui->pageTittle->setText(title);把传入的标题设置给标题标签;ui->musicImageLabel->setPixmap(QPixmap(image));把传入的图片路径对应的图片设置给封面图标签;ui->musicImageLabel->setScaledContents(true);让封面图自动缩放填充,保证图片显示效果。

  • 页面关联:在QQMusic::initUI中设置三个页面的标题和背景图,通过QStackedWidget管理页面切换。QStackedWidget就像一个页面管理器,能方便地在不同页面之间切换。

4. 核心要点总结

  • 复用设计:采用通用布局设计,通过自定义控件实现页面复用,减少了代码的重复编写。
  • 初始化便捷:利用setCommonPageUI方法进行页面初始化,能快速设置标题和封面图。
  • 页面管理:通过QStackedWidget管理页面切换,提高了多页面显示的效率。

四、自定义ListItemBox

1. ListItemBox页面分析

  • 功能:作为QListWidget的列表项,用来显示歌曲信息和收藏按钮。
  • 组件构成
    • musicNameBox:里面有收藏按钮(likeBtn)、歌曲名称、VIP/SQ标签。
    • musicSingerBox:显示歌手名称。
    • albumBox:显示专辑名称。
    • 采用水平弹簧控制布局对齐,让界面元素排列更整齐。

2. ListItemBox页面布局

  • 尺寸:整体尺寸是800*45,采用水平布局,分为三部分,宽度分别是380、200和剩余空间,合理分配空间显示不同信息。
  • 样式设置
    • VIP/SQ标签有边框和颜色区分,能让你快速识别歌曲的特殊属性。收藏按钮无边框,鼠标悬停时背景色变成#EFEFEF,有明显的交互反馈。

3. ListItemBox显示测试

  • 集成到CommonPage
// commonpage.cpp
void CommonPage::setCommonPageUI(const QString &title, const QString &image) {// ...ListItemBox* listItemBox = new ListItemBox(this);QListWidgetItem* listWidgetItem = new QListWidgetItem(ui->pageMusicList);listWidgetItem->setSizeHint(QSize(ui->pageMusicList->width(), 45));ui->pageMusicList->setItemWidget(listWidgetItem, listItemBox);// ...
}

CommonPage::setCommonPageUI方法中,创建一个ListItemBox对象,同时创建一个QListWidgetItem对象。listWidgetItem->setSizeHint(QSize(ui->pageMusicList->width(), 45));设置列表项的大小提示。最后通过ui->pageMusicList->setItemWidget(listWidgetItem, listItemBox);ListItemBox添加到QListWidget中显示。

4. 支持hover效果

// listitembox.cpp
void ListItemBox::enterEvent(QEvent *event) {Q_UNUSED(event);setStyleSheet("background-color:#EFEFEF");
}void ListItemBox::leaveEvent(QEvent *event) {Q_UNUSED(event);setStyleSheet("");
}

enterEvent方法在鼠标进入列表项时触发,把列表项的背景色设置为#EFEFEF。leaveEvent方法在鼠标离开列表项时触发,清除背景色设置,让列表项恢复原来的样子。这样能给用户明显的视觉反馈,知道鼠标当前的位置。

5. 核心要点总结

  • 布局合理:设计合理的界面布局,清晰显示歌曲信息和收藏按钮。
  • 集成方便:通过设置大小提示和添加到QListWidget,能方便地将ListItemBox集成到CommonPage中。
  • 交互增强:重写鼠标事件方法,实现hover效果,提升了用户的交互体验。

五、自定义MusicSlider

1. 功能与设计

  • 替代原生滑杆:自定义了一个水平进度条,由轨道(inLine)和进度条(outLine)组成,替代了原生的滑杆,能更好地满足特定的设计需求。
  • 视觉效果
    • 轨道背景色是#EBEEF5,进度条背景色是#1ECC94,没有边界,看起来更简洁美观。
    • 尺寸是800*20,进度条高度为4px,比例协调。

2. 交互实现

// musicslider.cpp
void MusicSlider::mousePressEvent(QMouseEvent *event) {currentPos = event->pos().x();moveSilder();
}void MusicSlider::mouseMoveEvent(QMouseEvent *event) {if (event->buttons() & Qt::LeftButton) {currentPos = event->pos().x();moveSilder();}
}void MusicSlider::mouseReleaseEvent(QMouseEvent *event) {Q_UNUSED(event);moveSilder();emit setMusicSliderPosition(currentPos * 1.0 / width());
}void MusicSlider::moveSilder() {currentPos = qMax(0, qMin(currentPos, width()));ui->outLine->setGeometry(0, 8, currentPos, 4);
}
  • 鼠标事件mousePressEvent在鼠标按下时记录鼠标相对于控件的x坐标,并调用moveSilder方法更新进度条。mouseMoveEvent在鼠标移动且左键按下时,同样更新坐标并调用moveSildermouseReleaseEvent在鼠标释放时,调用moveSilder更新进度条,然后发射setMusicSliderPosition信号,传递当前进度条的比例。
  • 信号槽:通过发射信号,关联到QQMusic更新播放位置,实现了进度条和音乐播放位置的同步。
  • 进度条更新moveSilder方法把currentPos限制在0到控件宽度范围内,然后根据这个位置更新outLine的几何位置,也就是更新进度条的显示长度。

3. 核心要点总结

  • 视觉优化:自定义水平进度条,优化了视觉效果,让界面更美观。
  • 交互实现:通过重写鼠标事件方法,实现了进度条的拖拽操作,方便用户控制音乐播放进度。
  • 功能交互:利用信号槽机制,将进度信息传递给上层模块,实现了进度条和音乐播放的交互。

六、自定义VolumeTool

1. 控件分析

  • 功能:是一个音量调节弹出窗口,包含静音按钮、滑杆和音量显示,方便用户调节音量。
  • 界面组成
    • silenceBtn:用于切换静音状态,图标会根据静音状态动态变化。
    • sliderBox:是垂直滑杆,里面有小圆球(sliderBtn)和音量比例显示。
    • 倒三角绘制:通过paintEvent手动绘制提示按钮位置,让界面更直观。

2. 界面布局

  • 尺寸:整体尺寸是100*350,采用弹出窗口样式,没有边框,带有阴影,看起来更美观。
  • 样式设置
    • 背景色是#FFFFFF,边框圆角为5px,滑杆轨道是#ECECEC,进度条是#1ECC94,滑块圆角为7px,整体界面风格统一。

3. 界面设置与交互

  • 弹出逻辑
// volumetool.cpp
void VolumeTool::showVolumeTool(const QPoint &pos) {move(pos.x() - width() / 2, pos.y());show();
}

showVolumeTool方法在点击主界面音量按钮时调用,根据传入的位置信息,把窗口移动到按钮下方居中的位置,然后显示窗口。

  • 静音按钮逻辑
// volumetool.cpp
void VolumeTool::onSilenceBtnClicked() {isMuted = !isMuted;ui->silenceBtn->setIcon(isMuted ? QIcon(":/images/silent.png") : QIcon(":/images/volumn.png"));emit setSilence(isMuted);
}

onSilenceBtnClicked方法在点击静音按钮时触发,切换isMuted标志位的状态。如果是静音状态,就把按钮图标设置为静音图标;如果是非静音状态,就设置为音量图标。然后发射setSilence信号,通知QMediaPlayer设置静音或取消静音。

  • 滑杆操作
// volumetool.cpp
bool VolumeTool::eventFilter(QObject *watched, QEvent *event) {if (watched == ui->sliderBox) {if (event->type() == QEvent::MouseMove) {QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);int y = mouseEvent->pos().y();int height = ui->sliderBox->height();volumeRatio = 1 - y * 1.0 / height;updateSlider();emit setMusicVolume(volumeRatio);}return true;}return QObject::eventFilter(watched, event);
}void VolumeTool::updateSlider() {int height = ui->sliderBox->height();int sliderY = (1 - volumeRatio) * height;ui->sliderBtn->move(0, sliderY - ui->sliderBtn->height() / 2);ui->volumeLabel->setText(QString::number(qRound(volumeRatio * 100)) + "%");
}

eventFilter方法是事件过滤器,当鼠标在sliderBox上移动时,计算鼠标位置对应的音量比例volumeRatio,调用updateSlider方法更新滑块位置和音量显示,然后发射setMusicVolume信号,将音量比例传递给播放器更新音量。updateSlider方法根据音量比例计算滑块的位置,移动滑块并更新音量显示。

4. 核心要点总结

  • 界面设计:设计弹出式音量调节窗口,提供了直观的音量调节界面。
  • 静音控制:实现了静音按钮的切换逻辑和图标更新,方便用户控制静音状态。
  • 滑杆交互:通过事件过滤器处理滑杆操作,实时更新音量显示并发送音量信号,实现了音量的灵活调节。

📣 结语

感谢你耐心看完,这里是我送给你(也给我自己)的几句话:

  • 更好的自己,而不是完美的别人。
  • 做你喜欢的事情容易,但做你该做的事,才叫成长。
  • 努力让自己变得切实,而不只是一团混乱的情感。
  • 有时候放弃容易,但坚持一定很酷。
  • 知识不是力量,只有应用知识才是真正的力量。
  • 有两种选择活着:忙着死,或忙着活。坚持住就能突出,坚持不住就会被淘汰。你的野心很大,所以你没资格停下来。
  • 白天向生活投降,夜晚忠于自己。

如果你觉得我写的不错,记得给我点赞,收藏 和 关注哦(。・ω・。)

让我们一起加油,向美好的未来奔去。让我们从一无所知的新手逐渐成为专家。为自己点赞吧!


相关文章:

【QQmusic自定义控件实现音乐播放器核心交互逻辑】第三章

&#x1f339; 作者: 云小逸 &#x1f91f; 个人主页: 云小逸的主页 &#x1f91f; motto: 要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前&#xff0c;其次就是现在&…...

基于图扑 HT 实现的智慧展馆数字孪生应用

在当今数字化时代&#xff0c;智慧展览馆作为传统展览场所的创新升级形态&#xff0c;借助前沿科技与现代化管理理念&#xff0c;实现了全方位的数字化、智能化转型。图扑软件凭借其自主研发的 HT 技术在智慧展馆领域取得了卓越成果&#xff0c;为城市基础设施数字化应用带来了…...

从线性到非线性:简单聊聊神经网络的常见三大激活函数

大家好&#xff0c;我是沛哥儿&#xff0c;我们今天一起来学习下神经网络的三个常用的激活函数。 引言&#xff1a;什么是激活函数 激活函数是神经网络中非常重要的组成部分&#xff0c;它引入了非线性因素&#xff0c;使得神经网络能够学习和表示复杂的函数关系。 在神经网络…...

重生之--js原生甘特图实现

需求&#xff1a; 一个树形结构&#xff0c;根据子节点的时间范围显示显示进度 &#xff0c;不同的时间范围对应不同的颜色 数据类型大概是这个样子的 甘特图 dom部分 首先要计算所有节点的 最大时间和最小时间 然后再计算每个甘特图的宽度 再计算他的偏移量 再计算颜色...

pnpm monoreop 打包时 node_modules 内部包 typescript 不能推导出类型报错

报错信息如下&#xff1a; ../../packages/antdv/components/pro-table/src/form-render.vue:405:1 - error TS2742: The inferred type of default cannot be named without a reference to .pnpm/scroll-into-view-if-needed2.2.31/node_modules/scroll-into-view-if-needed…...

告别默认配置!Xray自定义POC开发指南

文章涉及操作均为测试环境,未授权时切勿对真实业务系统进行测试! 下载与解压 官网地址: Xray GitHub Releases 根据系统选择对应版本: Windows:xray_windows_amd64.exe.zipLinux:xray_linux_amd64.zipmacOS:xray_darwin_amd64.zip解压后得到可执行文件(如 xray_linux_…...

websheet之 自定义函数

在线代码 {.is-success} 一、自定义函数约定 必须遵守本控件的自定函数约定才可以正常使用。 {.is-warning} 约定如下&#xff1a; 自定义类名称与函数名称一致。&#xff08;强制&#xff09;该类方法名称与函数名称一致&#xff0c;该方法是函数的入口。&#xff08;强制&am…...

Jenkins Pipeline 构建 CI/CD 流程

文章目录 jenkins 安装jenkins 配置jenkins 快速上手在 jenkins 中创建一个新的 Pipeline 作业配置Pipeline运行 Pipeline 作业 Pipeline概述Declarative PipelineScripted Pipeline jenkins 安装 安装环境&#xff1a; Linux CentOS 10&#xff1a;Linux CentOS9安装配置Jav…...

电脑技巧:路由器内部元器件介绍

目录 1. 处理器(CPU) 2. 内存(RAM) 3. 固态存储(Flash Memory) 4. 网络接口卡(NIC) 5. 电源模块 6. 散热系统 7. 无线天线 结语 路由器是我们日常上网的重要设备,今天我们就来深入了解路由器内部的各个元器件,了解它们是如何协同工作,一起来看看吧。 1. 处理器(CPU…...

ArrayUtils:数组操作的“变形金刚“——让你的数组七十二变

各位数组操控师们好&#xff01;今天给大家带来的是Apache Commons Lang3中的ArrayUtils工具类。这个工具就像数组界的"孙悟空"&#xff0c;能让你的数组随心所欲地变大、变小、变长、变短&#xff0c;再也不用对着原生数组的"死板"叹气了&#xff01; 一…...

电脑温度怎么看 查看CPU温度的方法

监测电脑温度对于保持硬件健康非常重要&#xff0c;特别是在进行高强度运算、游戏或超频等操作时。过高的温度可能导致硬件性能下降&#xff0c;甚至损坏。本篇文章将介绍查看电脑温度的4种方法。 一、使用Windows内置工具查看CPU温度 Windows系统本身并不直接提供查看CPU温度…...

【合新通信】---浸没式液冷光模块化学兼容性测试方法

一、测试目的与核心挑战 测试目标 验证冷媒&#xff08;氟化液、矿物油等&#xff09;与光模块材料的化学稳定性&#xff0c;确保长期浸没环境下无腐蚀、溶胀或性能衰减。关键风险点&#xff1a;密封材料&#xff08;如硅胶、环氧树脂&#xff09;的溶解或老化&#xff1b;金…...

shell 循环

shell 循环while语句,shell循环until语句在上一篇shell流程控制 1.shell循环until语句 until 条件 #当后面的条件表达式为假的时候的才循环,为真的时候就停止了 do 循环体 done [root@linux-server script]# cat until.sh (1) #!/bin/bash x=1 until [ $x -ge 10 ] 大于…...

【产品经理】常见的交互说明撰写方法

在产品原型设计中&#xff0c;交互说明是确保开发团队准确理解设计意图的关键文档。以下是常见的交互说明撰写方法及其应用场景&#xff0c;帮助您系统化地传达交互逻辑&#xff1a; 文字描述法 方法&#xff1a;用自然语言详细描述操作流程、反馈及规则。 适用场景&#xff…...

使用kubeadmin 部署k8s集群

成功搭建一个 Kubernetes 1.28.2 集群,包含以下组件和状态: 集群拓扑 1 个 Master 节点 IP:10.1.1.100 角色:control-plane 2 个 Worker 节点 Node2:10.1.1.101 Node3:10.1.1.102 核心组件状态 所有节点通过 kubectl get nodes 显示为 Ready。 核心 Pod(如 etc…...

二项式分布html实验

二项式分布html实验 本文将带你一步步搭建一个纯前端的二项分布 Monte-Carlo 模拟器。 只要一个 HTML 文件&#xff0c;打开就能运行&#xff1a; 动态输入试验次数 n、成功概率 p 与重复次数 m点击按钮立刻得到「模拟频数 vs 理论频数」柱状图随着 m 增大&#xff0c;两组柱状…...

[基础] Windows PCIe设备驱动框架与开发实践深度解析

Windows PCIe设备驱动框架与开发实践深度解析 1. PCIe设备驱动技术背景 PCI Express&#xff08;Peripheral Component Interrupt Express&#xff09;作为现代计算机系统的核心互连标准&#xff0c;其驱动程序开发涉及复杂的内核模式编程。Windows系统通过模块化的驱动架构支…...

面向智能家居安全的异常行为识别与应急联动关键技术研究与系统实现(源码+论文+部署讲解等)

需要资料&#xff0c;请文末系 一、平台介绍 3D家庭实景 - 动热力图 多模态看板 跌倒行为分析 二、论文内容 在这里插入图片描述](https://i-blog.csdnimg.cn/direct/2dfe7f45d3ce42399e0df9535870d26d.png) bash 摘要 Abstract第一章 绪论 1.1 研究背景与动机 o1.1.1…...

根据JSON动态生成表单表格

根据JSON动态生成表单表格 一. 子组件 DynamicFormTable.vue1,根据JSON数据动态生成表单表格,支持表单验证JS部分1.1,props数据1.2,表单数据和数据监听1.3,自动验证1.4,表单验证1.5,获取表单数据1.6,事件处理1.7,暴露方法给父组件2,HTML部分二,父组件1, 模拟数据2,…...

spring OncePerRequestFilter 作用

概要 OncePerRequestFilter 是 Spring Web 提供的一个抽象滤器基类&#xff0c;用于保证在一次 HTTP 请求的整个分派过程中&#xff0c;该滤器仅执行一次&#xff0c;无论该请求经历了多少次内部转发&#xff08;forward&#xff09;、包含&#xff08;include&#xff09;或错…...

关于开源大模型(如 LLaMA、InternLM、Baichuan、DeepSeek、Qwen 等)二次开发或训练经验的关键点和概述

以下是适合初学者理解的关于开源大模型&#xff08;如 LLaMA、InternLM、Baichuan、DeepSeek、Qwen 等&#xff09;二次开发或训练经验的关键点和概述&#xff0c;&#xff1a; 关键点&#xff1a; 研究表明&#xff0c;二次开发通常涉及微调模型以适应特定任务&#xff0c;需…...

promethus基础

1.下载prometheus并解压 主要配置prometheus.yml文件 在scrape_configs配置项下添加配置(hadoop202是主机名)&#xff1a; scrape_configs: job_name: ‘prometheus’ static_configs: targets: [‘hadoop202:9090’] 添加 PushGateway 监控配置 job_name: ‘pushgateway’…...

26考研 | 王道 | 数据结构 | 第八章 排序

第八章 排序 文章目录 第八章 排序**8.1** 排序的基本概念**8.2 插入排序****8.2.1 直接插入排序****8.2.2 折半插入排序****8.2.3 希尔排序** 8.3 交换排序8.3.1 冒泡排序8.3.2 快速排序 8.4 选择排序8.4.1 简单选择排序8.4.2 堆排序堆的概念&#xff1a;建立大根堆的代码堆排…...

SecMulti-RAG:兼顾数据安全与智能检索的多源RAG框架,为企业构建不泄密的智能搜索引擎

本文深入剖析SecMulti-RAG框架&#xff0c;该框架通过集成内部文档库、预构建专家知识以及受控外部大语言模型&#xff0c;并结合保密性过滤机制&#xff0c;为企业提供了一种平衡信息准确性、完整性与数据安全性的RAG解决方案&#xff0c;同时有效控制部署成本。 企业环境中A…...

kubesphere 单节点启动 etcd 报错

kubekey安装 ./kk create cluster -f config-sample.yaml --with-local-storage 时报错 etcd health check failed: Failed to exec command: sudo -E /bin/bash -c "export ETCDCTL_API2;export ETCDCTL_CERT_FILE/etc/ssl/etcd/ssl/admin-node1.pem;export ETCDCTL_KEY_…...

femap许可常见问题及解决方案

在使用Femap进行电磁仿真分析时&#xff0c;许可证管理是一个关键环节。然而&#xff0c;许多用户在许可证使用过程中可能会遇到各种问题。本文旨在解答关于Femap许可的常见疑问&#xff0c;并提供相应的解决方案&#xff0c;帮助您更顺畅地使用Femap许可证。 一、常见问题 许…...

游戏引擎学习第244天: 完成异步纹理下载

启动并运行游戏&#xff0c;注意到我们的纹理没有被下载 我们将继续完成游戏的开发。昨天&#xff0c;我们已经实现了多线程的纹理下载&#xff0c;但并没有时间调试它&#xff0c;因此纹理下载功能目前并没有正常工作。我们只是写了相关的代码&#xff0c;但由于大部分时间都…...

【安全扫描器原理】TCP/IP协议编程

【安全扫描器原理】TCP/IP协议编程 1.概述2.Windows Socket结构3.Windows socket转换类函数4.Windows Socket通信类函数 1.概述 TCP/IP协议是目前网络中使用最广泛的协议&#xff0c;Socket称为“套接口”​&#xff0c;最早出现在Berkeley Unix中&#xff0c;最初只支持TCP/I…...

Cuda-GDB Frame Unwind 管理(未完.)

在计算机编程中&#xff0c;Frame Unwind&#xff08;栈展开&#xff09; 是指函数调用栈的逆向操作&#xff0c;即在函数返回或异常发生时&#xff0c;系统逐层释放栈帧&#xff08;Stack Frame&#xff09;、恢复调用上下文的过程。以下是详细解释及其在 GPU编程&#xff08;…...

如何在IDEA中高效使用Test注解进行单元测试?

在软件开发过程中&#xff0c;单元测试是保证代码质量的重要手段之一。而IntelliJ IDEA作为一款强大的Java开发工具&#xff0c;提供了丰富的功能来支持JUnit测试&#xff0c;尤其是通过Test注解可以快速编写和运行单元测试。那么&#xff0c;如何在IDEA中高效使用Test注解进行…...

什么是访客鉴权?全面解析核心原理与CC防护应用实践

一、访客鉴权是什么&#xff1f; 访客鉴权&#xff08;Visitor Authentication and Authorization&#xff09;是系统对访问者进行身份验证和权限控制的过程&#xff0c;确保只有合法用户能够访问特定资源或执行特定操作。其核心目标是确认身份、控制权限、保障数据安全&#…...

DeepSeek大模型应用学习通知

随着人工智能在各领域深度融合发展&#xff0c;DeepSeek大模型迅速火爆全网&#xff0c;清华大学以最快的速度发布了DeepSeek从入门到精通使用技巧&#xff0c;能够更好的助力于企业和个人参与到AI研究和应用中&#xff0c;对于AI行业创新有重要意义&#xff0c;被誉为国运级的…...

时间序列预测模型比较分析:SARIMAX、RNN、LSTM、Prophet 及 Transformer

时间序列预测根据过去的模式预测未来事件。我们的目标是找出最佳预测方法&#xff0c;因为不同的技术在特定条件下表现出色。本文章将探讨各种方法在不同数据集上的表现&#xff0c;为你在任何情况下选择和微调正确的预测方法提供真知灼见。 我们将探讨五种主要方法&#xff1…...

快速了解redis,个人笔记

更多个人笔记&#xff1a;&#xff08;仅供参考&#xff0c;非盈利&#xff09; gitee&#xff1a; https://gitee.com/harryhack/it_note github&#xff1a; https://github.com/ZHLOVEYY/IT_note &#xff08;基于mac展示&#xff0c;别的可以参考&#xff09;接下来将直接…...

Dify依赖管理poetry切换为uv

Dify升级 1.3.0 后api的依赖管理从poetry切换为了 uv管理&#xff0c;但是官网暂时还没有更新。 升级 tag&#xff1a;Dify 1.3.0版本 在此记录一下 uv 依赖管理操作 使用方法 [重要事项] 在 v1.3.0 版本中&#xff0c;poetry 已被[ uv ](https://docs.astral.sh/uv/) 替代…...

VGA 接口静电防护方案

VGA(Video Graphics Array)即视频图形阵列&#xff0c;具有分辨率高、显示速 率快、颜色丰富等优点&#xff0c;亦称为 D-Sub 接口&#xff0c;在彩色显示器领域得到了广 泛的应用&#xff0c; 如笔记本、投影仪、LCD 液晶显示屏 等。VGA 接口主要用于连接 计算机与显示设备。当…...

MySQL 详解之用户、权限与审计:保障数据安全的基石

在数据库系统中,数据是核心资产,对其的访问必须受到严格控制。谁能连接到数据库?他们能看到哪些数据?能执行哪些操作(读、写、修改结构)?系统中的所有操作是否被记录以便追溯?这正是用户管理、权限系统和审计机制需要解决的问题。 在 MySQL 中: 用户 (Users): 负责认…...

力扣面试150题--环形链表和两数相加

Day 32 题目描述 思路 采取快慢指针 /*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ public class Solution {public boolean hasCycle(ListNod…...

HMI与组态,自动化的“灵珠”和“魔丸”

在现代工业自动化领域&#xff0c;组态&#xff08;Configuration&#xff09;和人机界面&#xff08;HMI&#xff0c;Human-Machine Interface&#xff09;是两个核心概念&#xff0c;它们在智能化控制系统中发挥着至关重要的作用。尽管这两者看似简单&#xff0c;但它们的功能…...

AbMole| CU-CPT-8m(CAS号125079-83-6;目录号M9746)

CU-CPT-8m是一种特异性的TLR8&#xff08;toll-like receptor 8&#xff09;拮抗剂&#xff0c;其IC50值为67 nM&#xff0c;Kd值为220 nM。 生物活性 CU-CPT-8m是一种特异性的TLR8&#xff08;toll-like receptor 8&#xff09;拮抗剂&#xff0c;其IC50值为67 nM&#xff0c;…...

【网络入侵检测】基于源码分析Suricata的PCAP模式

【作者主页】只道当时是寻常 【专栏介绍】Suricata入侵检测。专注网络、主机安全,欢迎关注与评论。 1. 概要 👋 本文聚焦于 Suricata 7.0.10 版本源码,深入剖析其 PCAP 模式的实现原理。通过系统性拆解初始化阶段的配置流程、PCAP 数据包接收线程的创建与运行机制,以及数据…...

【滑动窗口+哈希表/数组记录】Leetcode 438. 找到字符串中所有字母异位词

题目要求 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的异位词的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 字母异位词是通过重新排列不同单词或短语的字母而形成的单词或短语&#xff0c;并使用所有原字母一次。 示例 1 输入&#xff1a;s…...

uniapp自定义封装tabbar

uniapp自定义封装tabbar 开发原因: 有很多时候 小程序并没有其类目 需要通过配置发布审核&#xff0c; ps&#xff1a;需要去掉项目pages.json tabbar配置&#xff0c;不然重进会显示默认&#xff0c;跳转页面不能uni.switchTab。 组件tabbar <template><viewclass&…...

uni-app云开发总结

uni-app云开发总结 云开发无非就三个概念&#xff1a;云数据库、云函数、云存储 uni-app中新增了一个概念叫做云对象&#xff0c;它其实就是云函数的加强版&#xff0c;它是导出的一个对象&#xff0c;对象中可以包含多个操作数据库的函数&#xff0c;接下来咱们就详细对uni-…...

uniapp-商城-37-shop 购物车 选好了 进行订单确认3 支付栏

支付栏 就是前面用的 car-Layout 在shop也用来这个组件 只是在那里用来的是购物车。 1、 样式 我们开始进入这个页面是点击的shop的购物篮 到这里就变成了支付栏 其实他们是同一个组件 只是做了样式区分 2、具体看看样式和代码 2.1 消失了购物车和改变了按钮名字 如何…...

搜索二叉树-key的搜索模型

二叉搜索树(Binary Search Tree, BST)是一种重要的数据结构&#xff0c;它有两种基本模型&#xff1a;Key模型和Key/Value模型。 一、Key模型 1.基本概念 Key模型是二叉搜索树中最简单的形式&#xff0c;每个节点只存储一个键值(key)&#xff0c;没有额外的数据值(value)。这…...

Qt ModbusSlave多线程实践总结

最近项目中用到了ModbusSlave&#xff0c;也就是Modbus从设备的功能&#xff0c;之前用的基本都是master设备&#xff0c;所以读取数据啥的用单线程就行了&#xff0c;用 void WaitHelper::WaitImplByEventloop(int msec) {QEventLoop loop;QTimer::singleShot(msec, &loop…...

Leetcode刷题记录18——接雨水

题源&#xff1a;https://leetcode.cn/problems/trapping-rain-water/description/?envTypestudy-plan-v2&envIdtop-100-liked 题目描述&#xff1a; 思路一&#xff1a; &#x1f31f; 本题核心思想&#xff1a;木桶效应 每个位置的“桶”&#xff1a;假设每个柱子的位…...

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤

以下是在 IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤&#xff1a; 步骤 1&#xff1a;创建 Maven Web 项目 新建项目 File -> New -> Project → 选择 Maven → 勾选 Create from archetype → 选择 maven-archetype-webapp。输入 GroupId&#xff08;如 com.examp…...

全球玻璃纸市场深度洞察:环保浪潮下的材料革命与产业重构(2025-2031)

一、行业全景&#xff1a;从传统包装到绿色经济的战略支点 玻璃纸&#xff08;Cellulose Film&#xff09;&#xff0c;即再生纤维素薄膜&#xff0c;以木浆、棉浆等天然纤维素为原料&#xff0c;通过碱化、黄化、成型等工艺制成&#xff0c;兼具透明性、柔韧性及100%生物降解性…...