Qt实现简易音乐播放器

 使用Qt6实现简易音乐播放器,效果如下:

github:

Gabriel-gxb/MusicPlayer: qt6实现简易音乐播放器

    

一、整体架构

基于Qt框架构建

整个音乐播放器程序以Qt框架为基础进行开发。Qt提供了丰富的类库和工具,方便开发者构建图形用户界面(GUI)以及处理多媒体等功能。

以MainWindow类为核心

  1.1. 功能集成点
      1.MainWindow类是程序的核心,集成了音乐播放器的各种功能逻辑,包括界面显示、用户交互处理、多媒体播放控制等。

  2.2. 继承关系
      1.继承自QMainWindow,这使得MainWindow能够利用QMainWindow的特性,如默认的菜单栏、工具栏、状态栏布局等。通过这种继承关系,可以在MainWindow类中方便地添加自定义的界面元素和功能。

功能模块划分

  1.1. 多媒体播放模块
      1.以QMediaPlayer类为中心,该类负责音乐文件的播放操作。同时创建QAudioOutput对象与QMediaPlayer关联,以处理音频输出相关的功能,如设置音量等。

  2.2. 界面显示模块
      1.包含各种QWidget相关的界面元素,如QPushButton(按钮)、QListWidget(列表部件)、QLabel(标签)、QSlider(滑块)等。这些界面元素用于展示音乐信息(如歌曲名称、播放时间、音量等),以及提供用户交互操作(如播放、暂停、添加文件、切换歌曲、调整音量等)。
      2.利用paintEvent函数绘制界面背景等自定义的绘制操作。

  3.3. 用户交互模块
      1.通过信号与槽机制将界面元素的交互事件(如按钮点击、滑块移动等)与相应的功能函数连接起来。例如,当用户点击播放按钮时,会触发on_pushButton_start_clicked函数来控制音乐的播放或暂停;当滑块移动时,会触发相应的sliderMoved或valueChanged函数来调整音乐播放的位置或音量等。

  4.4. 数据管理模块
      1.在程序中通过QListWidgetItem存储音乐文件相关信息,如文件名和文件路径(以QUrl形式存储在Qt::UserRole自定义数据中)。这些数据在程序运行过程中起到了管理音乐文件列表、获取当前播放文件等作用。

    

二、基本布局

在布局中,使按钮隐藏边框的样式表内容为:

*{border: none;
}

使ListWidget变为透明的样式表内容为:

*{background-color: transparent
}

     

三、代码注释

.h文件中代码:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QtMultimedia/qmediaplayer.h>QT_BEGIN_NAMESPACEclass QLabel;
class QListWidgetItem;namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;QMediaPlayer *player;bool isLoop = false;QLabel *label_volume;QLabel *label_loop;QString m_durationTime;QString m_positionTime;// QWidget interface
protected:virtual void paintEvent(QPaintEvent *event) override;private slots:void on_pushButton_add_clicked();void on_pushButton_start_clicked(bool check);void on_listWidget_itemClicked(QListWidgetItem *item);void on_listWidget_itemDoubleClicked(QListWidgetItem *item);void on_pushButton_volume_clicked(bool checked);void on_horizontalSlider_sliderMoved(int position);void on_horizontalSlider_sliderPressed();void on_verticalSlider_valueChanged(int value);void on_pushButton_front_clicked();void on_pushButton_back_clicked();void on_pushButton_mode_clicked(bool checked);void on_horizontalSlider_valueChanged(int value);
};#endif // MAINWINDOW_H

.cpp文件中代码:

#include "mainwindow.h"
#include "./ui_mainwindow.h"// 包含用于文件对话框操作的头文件
#include <QFileDialog>
// 包含用于绘制事件相关的头文件
#include <QPaintEvent>
// 包含用于绘图操作(如画图工具类)的头文件
#include <QPainter>
// 包含Qt多媒体相关的头文件
#include <QtMultimedia>// MainWindow类的构造函数,用于初始化MainWindow对象
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{// 使用UI设计文件中的setupUi函数来初始化界面ui->setupUi(this);// 设置主窗口的大小为宽度1000,高度700resize(1000, 700);// 创建一个QMediaPlayer对象,this表示该对象的父对象为MainWindowplayer = new QMediaPlayer(this);// 创建一个QAudioOutput对象,与前面创建的QMediaPlayer对象关联QAudioOutput *audioOutput = new QAudioOutput(player);player->setAudioOutput(audioOutput);// 创建一个QLabel对象用于显示音量相关信息,初始文本包含当前音量值(从垂直滑块获取)label_volume = new QLabel("当前音量:" + QString("%1").arg(ui->verticalSlider->value()), this);// 设置标签的固定宽度为80像素label_volume->setFixedWidth(80);// 将音量标签添加到状态栏的永久部件中,使其始终显示ui->statusBar->addPermanentWidget(label_volume);// 创建一个QLabel对象用于显示循环相关信息,初始文本为"当前模式:列表循环"label_loop = new QLabel("当前模式:列表循环", this);// 设置标签的固定宽度为200像素label_loop->setFixedWidth(200);// 将循环标签添加到状态栏中ui->statusBar->addWidget(label_loop);// 设置状态栏的样式表,使状态栏中的项目没有边框ui->statusBar->setStyleSheet(QString("QStatusBar::item{border:0px}"));// 当QMediaPlayer的播放状态发生改变时(开始播放或停止播放)的连接操作// 当playing为true表示正在播放,false表示停止播放// 使用lambda表达式作为槽函数,根据播放状态更新播放按钮的选中状态和水平滑块的可用性connect(player, &QMediaPlayer::playingChanged, this, [&](bool playing) {ui->pushButton_start->setChecked(!playing);  //播放按钮状态ui->horizontalSlider->setEnabled(true);  //设置进度条可拖拽});// 当QMediaPlayer的播放文件发生改变时(例如切换到新的音频或视频文件)的连接操作// media是新的播放文件的QUrl对象// 使用lambda表达式作为槽函数,根据新的播放文件更新歌曲名称标签的显示内容connect(player, &QMediaPlayer::sourceChanged, this, [&](const QUrl &media) {ui->label_info->setText(media.fileName());  //设置歌曲名称});// 当QMediaPlayer的源数据发生变化时(例如音频或视频的元数据发生改变)的连接操作// 使用lambda表达式作为槽函数,处理元数据变化相关的操作connect(player, &QMediaPlayer::metaDataChanged, this, [&]() {// 获取元数据对象QMediaMetaData metaData = player->metaData();// 获取元数据中的缩略图图像数据(如果存在)QVariant metaImg = metaData.value(QMediaMetaData::ThumbnailImage);if (metaImg.isValid()) {// 将图像数据转换为QImage对象QImage img = metaImg.value<QImage>();// 将QImage转换为QPixmap对象,并根据部件宽度缩放图像QPixmap pix = QPixmap::fromImage(img);ui->label_pic->setPixmap(pix.scaledToWidth(ui->widget->width()));} else {// 如果没有有效图像,清除标签上的图像显示ui->label_pic->clear();}});// 当QMediaPlayer的播放源时长发生变化时(例如切换到新的音频或视频文件,其时长与之前不同)的连接操作// duration是新的播放时长(以毫秒为单位)// 使用lambda表达式作为槽函数,根据新的时长更新水平滑块的最大范围,并计算和显示总时长connect(player, &QMediaPlayer::durationChanged, this, [&](qint64 duration) {ui->horizontalSlider->setMaximum(duration);int sec = duration / 1000;int min = sec / 60;sec %= 60;m_durationTime = QTime(0, min, sec).toString("mm:ss");ui->label_time->setText(m_positionTime + "/" + m_durationTime);});// 当QMediaPlayer的播放位置发生变化时(例如播放过程中时间轴的推进)的连接操作// position是新的播放位置(以毫秒为单位)// 使用lambda表达式作为槽函数,根据新的播放位置更新水平滑块的滑块位置,并计算和显示当前播放时间connect(player, &QMediaPlayer::positionChanged, this, [&](qint64 position) {if (ui->horizontalSlider->isSliderDown())return;ui->horizontalSlider->setSliderPosition(position);int sec = position / 1000;int min = sec / 60;sec %= 60;m_positionTime = QTime(0, min, sec).toString("mm:ss");ui->label_time->setText(m_positionTime + "/" + m_durationTime);});
}// MainWindow类的析构函数,用于释放ui对象占用的内存
MainWindow::~MainWindow()
{delete ui;
}
// paintEvent函数用于处理主窗口的绘制事件
// 重写QWidget的paintEvent函数
void MainWindow::paintEvent(QPaintEvent *event)
{// 创建一个QPainter对象,用于在主窗口(this表示当前的MainWindow对象)上进行绘制操作QPainter painter(this);// 创建一个QPixmap对象,加载指定资源路径(":/bk",这是Qt的资源系统路径)下的图像QPixmap pixmap(":/bk");// 将图像按照主窗口的大小进行缩放,忽略宽高比并使用平滑变换pixmap = pixmap.scaled(size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);// 在主窗口的坐标(0, 0)处绘制缩放后的图像painter.drawPixmap(0, 0, pixmap);// 调用父类(QMainWindow)的paintEvent函数,以确保默认的绘制操作也能执行return QMainWindow::paintEvent(event);
}// 当名为pushButton_add的按钮被点击时调用此函数
void MainWindow::on_pushButton_add_clicked()
{// 获取当前的工作目录路径QString curPath = QDir::currentPath();// 设置文件选择对话框的标题QString title = "选择音频文件";// 设置文件选择对话框的文件过滤器,只显示扩展名为.mp3的音频文件QString filter = "音频文件(*.mp3)";// 弹出文件选择对话框,允许用户选择多个文件,返回所选文件的路径列表QStringList fileList = QFileDialog::getOpenFileNames(this, title, curPath, filter);// 如果没有选择任何文件,则直接返回,不进行后续操作if (fileList.size() < 1) return;// 遍历所选文件的路径列表for (int i = 0; i < fileList.size(); i++) {// 获取当前遍历到的文件路径QString aFile = fileList[i];// 创建一个QFileInfo对象,用于获取文件的相关信息(如文件名等)QFileInfo info(aFile);// 创建一个QListWidgetItem对象,用于在列表部件(listWidget)中显示文件名QListWidgetItem *item = new QListWidgetItem(info.fileName());// 将文件的本地路径转换为QUrl对象,并将其作为用户自定义数据(Qt::UserRole)存储在列表项中item->setData(Qt::UserRole, QUrl::fromLocalFile(aFile));// 将创建好的列表项添加到列表部件(listWidget)中ui->listWidget->addItem(item);}
}
// 当名为pushButton_start的按钮被点击时调用此函数,check表示按钮的选中状态
void MainWindow::on_pushButton_start_clicked(bool check)
{// 获取列表部件(listWidget)中的当前选中项QListWidgetItem *item = ui->listWidget->currentItem();// 获取当前选中项中存储的文件路径(以QUrl形式)auto url = item->data(Qt::UserRole).toUrl();// 如果播放器的当前播放源与当前选中项的文件路径不同,则设置播放器的播放源为当前选中项的文件路径if (player->source()!= url)player->setSource(url);// 如果按钮未被选中(即check为false,表示要开始播放)if (!check) {// 设置播放按钮的图标为暂停图标(":/D:/Apps/qIcon/pause.png")ui->pushButton_start->setIcon(QIcon(":/D:/Apps/qIcon/pause.png"));// 调用播放器的play函数开始播放player->play();}// 如果按钮被选中(即check为true,表示要暂停播放)else {// 设置播放按钮的图标为播放图标(":/D:/Apps/qIcon/play.png")ui->pushButton_start->setIcon(QIcon(":/D:/Apps/qIcon/play.png"));// 调用播放器的pause函数暂停播放player->pause();}
}// 当列表部件(listWidget)中的项目被点击时调用此函数,item为被点击的项目指针
void MainWindow::on_listWidget_itemClicked(QListWidgetItem *item)
{// Q_UNUSED宏用于标记未使用的参数,这里表示虽然有item参数但在函数内未使用Q_UNUSED(item);// 启用播放按钮,使其可被点击ui->pushButton_start->setEnabled(true);// 启用向前按钮(pushButton_front),使其可被点击ui->pushButton_front->setEnabled(true);// 启用向后按钮(pushButton_back),使其可被点击ui->pushButton_back->setEnabled(true);
}
// 当列表部件(listWidget)中的项目被双击时调用此函数,item为被双击的项目指针
void MainWindow::on_listWidget_itemDoubleClicked(QListWidgetItem *item)
{// 获取被双击项目中存储的文件路径(以QUrl形式)auto url = item->data(Qt::UserRole).toUrl();// 设置播放器的播放源为被双击项目的文件路径player->setSource(url);// 设置播放按钮的图标为暂停图标(":/D:/Apps/qIcon/pause.png")ui->pushButton_start->setIcon(QIcon(":/D:/Apps/qIcon/pause.png"));// 调用播放器的play函数开始播放player->play();
}
// 当名为pushButton_volume的按钮被点击时调用此函数,checked表示按钮的选中状态
void MainWindow::on_pushButton_volume_clicked(bool checked)
{// 根据按钮的选中状态设置垂直滑块(verticalSlider)是否可见ui->verticalSlider->setVisible(checked);
}
// 当水平滑块(horizontalSlider)被移动时调用此函数,position为滑块的新位置
void MainWindow::on_horizontalSlider_sliderMoved(int position)
{// 设置播放器的播放位置为滑块的新位置(以毫秒为单位)player->setPosition(position);
}
// 当水平滑块(horizontalSlider)被按下时调用此函数
void MainWindow::on_horizontalSlider_sliderPressed()
{// 设置播放器的播放位置为水平滑块的当前值(以毫秒为单位)player->setPosition(ui->horizontalSlider->value());
}// 当水平滑块(horizontalSlider)的值发生改变时调用此函数,value为滑块的新值
void MainWindow::on_horizontalSlider_valueChanged(int value)
{// 如果当前播放时间等于总播放时间if (m_positionTime == m_durationTime) {// 如果处于循环播放模式(isLoop为true)if (isLoop)// 将播放器的播放位置设置为0,即重新开始播放player->setPosition(0);else// 否则点击向后按钮(pushButton_back),切换到下一个音频文件(根据pushButton_back的逻辑)ui->pushButton_back->click();}
}// 当垂直滑块(verticalSlider)的值发生改变时调用此函数,value为滑块的新值
void MainWindow::on_verticalSlider_valueChanged(int value)
{// 设置播放器音频输出的音量,将滑块的值转换为0到1之间的浮点数(因为音量范围是0.0到1.0)player->audioOutput()->setVolume(value / 100.0);// 更新音量标签的文本,显示当前音量值(从垂直滑块获取)label_volume->setText("当前音量:" + QString("%1").arg(ui->verticalSlider->value()));// 如果垂直滑块的值为0(即音量为0)if (ui->verticalSlider->value() == 0)// 设置音量按钮的图标为静音图标(":/D:/Apps/qIcon/静音.png")ui->pushButton_volume->setIcon(QIcon(":/D:/Apps/qIcon/静音.png"));else// 否则设置音量按钮的图标为音量图标(":/D:/Apps/qIcon/音量.png")ui->pushButton_volume->setIcon(QIcon(":/D:/Apps/qIcon/音量.png"));
}
// 当名为pushButton_front的按钮被点击时调用此函数
void MainWindow::on_pushButton_front_clicked()
{// 获取列表部件(listWidget)中的当前行索引int curRow = ui->listWidget->currentRow();// 如果当前行是第一行(索引为0)if (curRow == 0)// 将当前行设置为最后一行(列表部件的行数减1)curRow = ui->listWidget->count() - 1;else// 否则将当前行减1,即切换到上一行curRow--;// 设置列表部件的当前行为新的行索引ui->listWidget->setCurrentRow(curRow);// 获取新的当前行项目中存储的文件路径(以QUrl形式)auto url = ui->listWidget->item(curRow)->data(Qt::UserRole).toUrl();// 设置播放器的播放源为新的文件路径player->setSource(url);// 调用播放器的play函数开始播放player->play();
}
// 当名为pushButton_back的按钮被点击时调用此函数
void MainWindow::on_pushButton_back_clicked()
{// 获取列表部件(listWidget)中的当前行索引int curRow = ui->listWidget->currentRow();// 如果当前行是最后一行(索引为列表部件的行数减1)if (curRow == ui->listWidget->count() - 1)// 将当前行设置为第一行(索引为0)curRow = 0;else// 否则将当前行加1,即切换到下一行curRow++;// 设置列表部件的当前行为新的行索引ui->listWidget->setCurrentRow(curRow);// 获取新的当前行项目中存储的文件路径(以QUrl形式)auto url = ui->listWidget->item(curRow)->data(Qt::UserRole).toUrl();// 设置播放器的播放源为新的文件路径player->setSource(url);// 调用播放器的play函数开始播放player->play();
}
// 当名为pushButton_mode的按钮被点击时调用此函数,checked表示按钮的选中状态
void MainWindow::on_pushButton_mode_clicked(bool checked)
{// 如果按钮被选中(即checked为true)if (checked) {// 更新循环模式标签的文本为"当前模式:单曲循环"label_loop->setText("当前模式:单曲循环");// 设置模式按钮的图标为单曲循环图标(":/D:/Apps/qIcon/单曲循环.png")ui->pushButton_mode->setIcon(QIcon(":/D:/Apps/qIcon/单曲循环.png"));// 设置循环标志为true,表示处于单曲循环模式isLoop = true;}else {// 更新循环模式标签的文本为"当前模式:列表循环"label_loop->setText("当前模式:列表循环");// 设置模式按钮的图标为列表循环图标(":/D:/Apps/qIcon/列表循环.png")ui->pushButton_mode->setIcon(QIcon(":/D:/Apps/qIcon/列表循环.png"));// 设置循环标志为false,表示处于列表循环模式isLoop = false;}
}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/13816.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GPT-4使用次数有上限吗?一文了解使用规则

GPT-4的推出&#xff0c;让越来越多的用户开始体验其卓越的功能。无论是用于日常需求还是专业内容制作&#xff0c;GPT-4的应用范围广泛&#xff0c;获得了用户的广泛赞誉。但是&#xff0c;在具体使用过程中&#xff0c;不少用户发现自己似乎触碰到了GPT-4的使用上限&#xff…

水波效果

水波效果指在计算机图形学中模拟水面波纹的视觉效果&#xff0c;通常用于游戏、动画或者其他虚拟场景中。主要用于体现水体的动态感&#xff0c;比如水的波动、反射、折射、透明等&#xff0c;可以让人感觉像真实的水一样流动闪耀。 核心特点就是&#xff1a; 动态波纹光学特…

Redis | 十大数据类型

文章目录 十大数据类型概述key操作命令数据类型命令及落地运用redis字符串&#xff08;String&#xff09;redis列表&#xff08;List&#xff09;redis哈希表&#xff08;Hash&#xff09;redis集合&#xff08;Set&#xff09;redis有序集合&#xff08;ZSet / SortedSet&…

Linux之安装docker

一、检查版本和内核是否合格 Docker支持64位版本的CentOS 7和CentOS 8及更高版本&#xff0c;它要求Linux内核版本不低于3.10。 检查版本 cat /etc/redhat-release检查内核 uname -r二、Docker的安装 1、自动安装 Docker官方和国内daocloud都提供了一键安装的脚本&#x…

【WebLogic】Oracle发布WebLogic 14c最新版本-14.1.2.0

根据Oracle官方产品经理的博客&#xff0c;Oracle于2024年12月20日正式对外发布了WebLogic 14c的第二个正式版本&#xff0c;版本号为 14.1.2.0.0 &#xff0c;目前官方已开放客户端下载。该版本除继续支持 Jakarta EE 8 版本外&#xff0c;还增加了对 Java SE 17&#xff08;J…

feign 远程调用详解

在平常的开发工作中&#xff0c;我们经常需要跟其他系统交互&#xff0c;比如调用用户系统的用户信息接口、调用支付系统的支付接口等。那么&#xff0c;我们应该通过什么方式进行系统之间的交互呢&#xff1f;今天&#xff0c;简单来总结下 feign 的用法。 1&#xff1a;引入依…

解决 npm : 无法加载文件 D:\nodeJS\node_global\npm.ps1,因为在此系统上禁止运行脚本。

问题 在我将nodeJS从18更新到22之后&#xff0c;我发现在黑窗口运行npm run dev&#xff0c;可以成功启动项目&#xff0c;但是在Cursor的终端中却报如下错误&#xff1a; PS D:\DESKTOP\项目\vue-ems-admain> npm run dev npm : 无法加载文件 D:\Users\Download\nodeJS\no…

快速对QWen2.5大模型进行微调

先看看训练结果&#xff1a; 目录 前言什么是LLaMA-Factory&#xff1f;安装LLaMA-Factory准备数据集配置微调参数运行微调脚本评估和保存模型使用微调后的模型可视化微调大模型总结 前言 在当今人工智能领域&#xff0c;大模型&#xff08;如LLaMA、GPT等&#xff09;的微调…

深入理解linux中的文件(下)

目录 一、语言级缓冲区和内核级缓冲区 二、C语音中的FILE* fp fopen(“./file.txt”,"w"): 四、理解磁盘结构&#xff1a; 物理结构 逻辑结构 五、未被打开的文件&#xff1a; 六、更加深入理解inode编号怎么找到文件&#xff1a; 七、对路径结构进行…

自动化测试、压力测试、持续集成

因为项目的原因&#xff0c;前段时间研究并使用了 SoapUI 测试工具进行自测开发的 api。下面将研究的成果展示给大家&#xff0c;希望对需要的人有所帮助。 SoapUI 是什么&#xff1f; SoapUI 是一个开源测试工具&#xff0c;通过 soap/http 来检查、调用、实现 Web Service 的…

BUU28 [GXYCTF2019]BabySQli1

常规万能密码&#xff0c;发现登不上去 过滤掉了or&#xff0c;&#xff0c;当尝试了n种方法以后&#xff0c;最关键的是发现()居然也被过滤了 哈哈&#xff0c;那玩个淡&#xff0c; 再搜wp&#xff01;&#xff01; 当输入admin的时候&#xff0c;提示密码错误&#xff0…

Zenoh在工业物联网场景中的性能研究

论文标题 中文标题&#xff1a;Zenoh在工业物联网场景中的性能研究 英文标题&#xff1a;On the performance of Zenoh in Industrial IoT Scenarios 作者信息 Miguel Barn, Luis Diez, Mihail Zverev, Jos R. Jurez, Ramn Agero Miguel Barn&#xff1a;Ikerlan技术研究中心…

一次奇怪的空指针问题分析:事务、死锁与隐式回滚

最近我们在排查一个诡异的 空指针异常&#xff0c;整个分析过程可以说是跌宕起伏&#xff0c;最终的结论也颇具隐蔽性。今天就把这个问题分享出来&#xff0c;希望对大家有所帮助。 问题现象 在系统中&#xff0c;我们有 单据 B&#xff0c;它通过一个 关联 ID 字段与 上级单…

掌握API和控制点(从Java到JNI接口)_37 JNI开发与NDK 05

*.so的入口函数&#xff1a;JNI_OnLoad() 执行System.loadLibrary()函数时&#xff0c; VM会反向调用*.so里的JNI_OnLoad()函数。用途有二&#xff1a; 1. VM询问此*.so使用的JNI版本编号。 2. VM要求*.so做一些初期设定工作(Initialization)&#xff0c;例如登记<函…

MySQL数据库 (三)- 函数/约束/多表查询/事务

目录 一 函数 (一 字符串函数 (二 数值函数 (三 日期函数 (四 流程函数 二 约束 (一 概述 (二 约束演示 (三 外键约束 三 多表查询 (一 多表关系 1 一对多&#xff08;多对一&#xff09; 2 多对多 3 一对一 (二 多表查询概述 (三 内连接 1 查询语法 2 代码实…

EGO-Planner文章解读(一)——论文原理和算法实现

在fastplanner中&#xff0c;ESDF 对于评估梯度大小和方向至关重要。然而轨迹优化过程只覆盖了 ESDF 更新范围的非常有限的子空间&#xff0c;计算全图的ESDF是非常冗余的。除此之外&#xff0c;在建图的时候只能看见障碍物的表面&#xff0c;看不见障碍物的后面/内部&#xff…

C语言——深入理解指针(1)

深入理解指针 内存和地址内存究竟该如何理解编址呢&#xff1f; 指针变量和地址取地址操作符&#xff08;&&#xff09;指针变量和解引用操作符&#xff08;*&#xff09;指针变量如何拆解指针类型解引用操作符 指针变量的大小 指针变量类型的意义指针的解引用指针-整数voi…

人人皆可创建自己的AI应用:DigitalOcean GenAI平台正式上线

近日海外知名云平台DigitalOcean宣布&#xff0c;DigitalOcean GenAI 平台现已全面开放——这是一个强大且易用的解决方案&#xff0c;将彻底改变团队创建和部署人工智能应用的方式。 这一新平台延续了 DigitalOcean 普及 AI 开发的使命&#xff0c;让独立开发者到大型团队都能…

4.攻防世界 unseping

进入题目页面如下 直接给出源码&#xff0c;开始代码审计 <?php // 高亮显示当前 PHP 文件的源代码&#xff0c;方便调试和查看代码结构 highlight_file(__FILE__);// 定义一个名为 ease 的类 class ease {// 定义私有属性 $method&#xff0c;用于存储要调用的方法名priv…

Llama最新开源大模型Llama3.1

Meta公司于2024年7月23日发布了最新的开源大模型Llama 3.1&#xff0c;这是其在大语言模型领域的重要进展。以下是关于Llama 3.1的详细介绍&#xff1a; 参数规模与训练数据 Llama 3.1拥有4050亿&#xff08;405B&#xff09;参数&#xff0c;是目前开源领域中参数规模最大的…