首页 > 其他分享 >QT多媒体开发(二):播放音频

QT多媒体开发(二):播放音频

时间:2024-12-22 12:26:26浏览次数:6  
标签:多媒体 QT void MainWindow player ui listWidget 播放 音频

简介

QMediaPlayer 可以用于播放经过压缩的音频文件,如 MP3 文件和 WMA 文件。QSoundEffect 可以 用于播放低延迟音效文件,例如无压缩的 WAV 文件。这两个类都可以用于播放本地文件和网络文件。

QMediaPlayer 与播放音频相关的接口函数如下:

void setAudioOutput(QAudioOutput *output) //设置一个音频输出设备
QAudioOutput *audioOutput() //返回播放器关联的音频输出设备信息
void setSource(const QUrl &source) //设置播放媒介来源,本地文件或网络文件
QUrl source() //当前播放的媒介来源
void setActiveAudioTrack(int index) //设置当前的音频轨道
void setPlaybackRate(qreal rate) //设置播放速度,1.0 表示正常速度
void setLoops(int loops) //设置播放的循环次数
QMediaPlayer::PlaybackState playbackState() //返回当前播放器状态
QMediaMetaData metaData() //返回当前媒介的元数据
QMediaPlayer::MediaStatus mediaStatus() //媒介状态(正在缓冲、已下载等),对于网络媒介比较有用
bool hasAudio() //当前媒介是否有音频
bool hasVideo() //当前媒介是否有视频
qint64 duration() //媒介的持续时间,单位为 ms 
void setPosition(qint64 position) //设置当前的播放位置,单位为 ms 
qint64 position() //返回当前的播放位置,单位为 ms 
void play() //开始播放
void pause() //暂停播放
void stop() //停止播放

一般使用步骤

1、创建QMediaPlayer 对象,使用函数setAudioOutput()设置一个音频输出设备,

2、使用函数setSource()设置播放媒介来源(可以是本地文件或网络文件)

3、使用函数数 play() 开始播放了。使用 pause()和 stop()函数可以暂停和停止播放。

QMediaPlayer常用的一些信号如下:

void durationChanged(qint64 duration) //媒介的持续时间发生变化
void mediaStatusChanged(QMediaPlayer::MediaStatus status) //媒介状态发生变化
void metaDataChanged() //媒介的元数据发生变化
void playbackStateChanged(QMediaPlayer::PlaybackState newState) //播放器状态发生变化
void positionChanged(qint64 position) //播放位置发生变化
void sourceChanged(const QUrl &media) //媒介来源发生变化

QMediaPlayer 在开始、暂停或停止播放时,播放器状态发生变化,会发playbackStateChanged()

信号,函数 playbackState()会返回当前播放器状态。

媒介有元数据,函数 metaData()可以返回当前媒介的元数据,重新设置媒介时会发射 metaDataChanged()信号。媒介的元数据是 QMediaMetaData 类型数据,元数据用“key-value”形式 的键值对表示,QMediaMetaData 主要有以下几个函数:

QList<QMediaMetaData::Key> keys() //返回键名称列表
QString stringValue(QMediaMetaData::Key key) //以字符串形式返回一个键的数据
QVariant value(QMediaMetaData::Key key) //以 QVariant 类型返回一个键的数据

媒介元数据的键用枚举类型 QMediaMetaData::Key 的常量表示,常见枚举常量表示的元数据的类型和意义如下:

示例程序

该播放器可以打开多个文件后连续播放,可以显示播 放进度、歌曲对应的图片,还可以设置静音、调节音 量。文件列表里的项可以被拖动,从而改变其在列表 里的位置。

主窗口头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include    <QMainWindow>
#include    <QtMultimedia>
#include    <QListWidgetItem>


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QMediaPlayer  *player;      //播放器
    bool    loopPlay=true;      //是否循环播放
    QString  durationTime;      //文件总长度,mm:ss字符串
    QString  positionTime;      //当前播放到位置,mm:ss字符串

    QUrl getUrlFromItem(QListWidgetItem *item);         //获取item的用户数据
    bool eventFilter(QObject *watched, QEvent *event);  //事件过滤处理
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    //自定义槽函数
    void do_stateChanged(QMediaPlayer::PlaybackState state);    //播放器状态发生变化
    void do_sourceChanged(const QUrl &media);   //文件发生变化
    void do_durationChanged(qint64 duration);   //文件长度发生变化
    void do_positionChanged(qint64 position);   //播放位置发生变化
    void do_metaDataChanged();          //元数据发生变化

    void on_btnAdd_clicked();      //添加按钮
    void on_btnPlay_clicked();     //播放按钮
    void on_btnPause_clicked();    //暂停按钮
    void on_btnStop_clicked();     //停止按钮
    void on_listWidget_doubleClicked(const QModelIndex &index);  //双击事件
    void on_btnClear_clicked();    //清空列表       
    void on_sliderVolumn_valueChanged(int value);   //音量条数值改变
    void on_btnSound_clicked();                     //点击音量按钮
    void on_sliderPosition_valueChanged(int value); //音频条数值改变
    void on_btnPrevious_clicked();          //上一曲
    void on_btnNext_clicked();              //下一曲
    void on_btnLoop_clicked(bool checked);  //循环播放
    void on_doubleSpinBox_valueChanged(double arg1);  //播放倍数
    void on_btnRemove_clicked();            //移除

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

这里为主窗口定义了一个事件过滤器eventFilter(),后续listWidget的事件委托给窗口来监视并处理。被监视对象(这里是listWidget)使用函数 installEventFilter()将自己注册给监视对象(Mainwindow),监视对象就是事件过滤器。监视对象重新实现函数 eventFilter(),对监视到的事件进行处理。

在主窗口构造函数中,listWidget将自己的事件通过installEventFilter()委托给主窗口的eventFilter,接下来创建了QMediaPlayer对象用于音频播放。创建的QAudioOutput指向默认音频输出设备,然后用 setAudioOutput() 函数设置播放器player的音频输出设备。最后为QMediaPlayer对象发射的一些信号设置了相关的槽函数用于界面响应和控制。

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->listWidget->installEventFilter(this); //安装事件过滤器,将窗口对象设置为事件过滤器
    ui->listWidget->setDragEnabled(true);           //允许拖放操作
    ui->listWidget->setDragDropMode(QAbstractItemView::InternalMove);   //列表项可移动

    player = new QMediaPlayer(this);   //创建音视频对象
    QAudioOutput *audioOutput = new QAudioOutput(this);   //音频输出,指向默认的音频输出设备
    player->setAudioOutput(audioOutput);    //设置音频输出
    connect(player,&QMediaPlayer::positionChanged,      //播放位置发生变化
            this, &MainWindow::do_positionChanged);

    connect(player,&QMediaPlayer::durationChanged,      //播放源长度发生变化
            this, &MainWindow::do_durationChanged);

    connect(player, &QMediaPlayer::sourceChanged,       //播放源发生变化
            this, &MainWindow::do_sourceChanged);

    connect(player, &QMediaPlayer::playbackStateChanged,    //播放器状态发生变化
            this,  &MainWindow::do_stateChanged);

    connect(player, &QMediaPlayer::metaDataChanged,     //元数据发生变化
            this,  &MainWindow::do_metaDataChanged);
}

//为listWidget安装事件过滤器,用于delete按键移除曲目
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if (event->type() != QEvent::KeyPress)      //不是KeyPress事件,退出
        return QWidget::eventFilter(watched,event);

    QKeyEvent *keyEvent=static_cast<QKeyEvent *>(event);
    if (keyEvent->key() != Qt::Key_Delete)      //按下的不是Delete键,退出
        return QWidget::eventFilter(watched,event);

    if (watched==ui->listWidget)    //判断被监视的对象是否是listWidget
    {
        QListWidgetItem *item= ui->listWidget->takeItem(ui->listWidget->currentRow());
        delete  item;
    }
    return true;    //表示事件已经被处理
}

QAudioOutput 是指向音频输出设备的类,它有如下几个函数:

void setDevice(const QAudioDevice &device) //设置一个 QAudioDevice 设备
QAudioDevice device() //返回当前的 QAudioDevice 设备
void setMuted(bool muted) //设置是否静音
bool isMuted() //是否静音了
void setVolume(float volume) //设置音量
float volume() //返回当前音量

一般创建QAudioOutput时就已经将其指向了默认的音频输出设备,如果要设置其他输出设备使用setDevice()函数,device()函数返回当前的输出设备,类型是QMediaDevices。

QMediaDevices 类提供系统内 的多媒体设备信息,它有以下几个静态函数,用于返回系统中的默认多媒体设备:

QAudioDevice QMediaDevices::defaultAudioInput() //返回默认的音频输入设备(如麦克风)信息
QAudioDevice QMediaDevices::defaultAudioOutput() //返回默认的音频输出设备(如音箱)信息
QCameraDevice QMediaDevices::defaultVideoInput() //返回默认的视频输入设备(如摄像头)信息

添加文件和移除文件

添加文件按钮的槽函数为on_btnAdd_clicked(),可以一次打开多个文件,文件被添加到界面上的列表组件 listWidget 里。

void MainWindow::on_btnAdd_clicked()
{//"添加"按钮,添加文件
    QString curPath=QDir::homePath();  //获取系统当前目录
    QString dlgTitle="选择音频文件";
    QString filter="音频文件(*.mp3 *.wav *.wma);;所有文件(*.*)";   //文件过滤器
    QStringList fileList=QFileDialog::getOpenFileNames(this,dlgTitle,curPath,filter);  //可以选择多个文件
    if (fileList.count()<1)
        return;

    for (int i=0; i<fileList.size();i++)  //依次将选择的文件添加到listWidget,并将文件路径保存到用户数据中
    {
        QString  aFile=fileList.at(i);
        QFileInfo  fileInfo(aFile);
        QListWidgetItem *aItem =new QListWidgetItem(fileInfo.fileName());
        aItem->setIcon(QIcon(":/images/images/musicFile.png"));
        aItem->setData(Qt::UserRole, QUrl::fromLocalFile(aFile));  //设置用户数据,QUrl对象
        ui->listWidget->addItem(aItem);
    }

    if (player->playbackState() != QMediaPlayer::PlayingState)   //添加后开始播放第一个文件
    {  //当前没有在播放,就播放第1个文件
        ui->listWidget->setCurrentRow(0);
        QUrl source= getUrlFromItem(ui->listWidget->currentItem());
        player->setSource(source);   //设置播放文件的路径
    }
    player->play();  //播放文件
}


QUrl MainWindow::getUrlFromItem(QListWidgetItem *item)
{
    QVariant itemData= item->data(Qt::UserRole);    //获取用户数据
    QUrl source =itemData.value<QUrl>();    //QVariant转换为QUrl类型
    return source;
}

根据选择的音频文件将其文件名添加到listWidget中,并设置其用户数据为QUrl类型的本地文件路径,后续播放listWidget中的曲目时,通过自定义函数getUrlFromItem从listWidget条目中获取到保存的本地文件路径,就可以使用setSource()函数设置播放媒介。

移除按钮对应的槽函数如下:

void MainWindow::on_btnRemove_clicked()
{//"移除"按钮,移除列表中的当前项
    int index =ui->listWidget->currentRow();
    if (index>=0)
    {
        QListWidgetItem *item= ui->listWidget->takeItem(index);   //new出来的对象移除时要使用delete
        delete item;
    }
}

在这个函数中,选择当前的listWidget进行删除,前面创建条目时使用的是new,那就对应使用delete删除

清空按钮对应的槽函数如下:

void MainWindow::on_btnClear_clicked()
{//"清空"按钮,清空播放列表
    loopPlay=false;     //防止do_stateChanged()里切换曲目
    ui->listWidget->clear();
    player->stop();
}

清空可以直接调用listWidget的clear()函数删除全部条目。

上一曲下一曲

这实际上还是对于listWidget中条目的处理,获取到当前的前一个/下一个条目后,取出条目中保存的用户数据(QUrl类型的本地文件路径)获得对应文件的路径,然后设置播放媒介即可。

void MainWindow::on_btnPrevious_clicked()
{//前一曲
    int curRow=ui->listWidget->currentRow();
    curRow--;
    curRow= curRow<0? 0:curRow;
    ui->listWidget->setCurrentRow(curRow);  //设置当前行

    loopPlay=false;     //暂时设置为false,防止do_stateChanged()里切换曲目
    player->setSource(getUrlFromItem(ui->listWidget->currentItem()));
    player->play();
    loopPlay=ui->btnLoop->isChecked();

//    if(ui->btnLoop->isChecked())
//    {
//        loopPlay=false;     //暂时设置为false,防止do_stateChanged()里切换曲目
//        player->setSource(getUrlFromItem(ui->listWidget->currentItem()));
//        player->play();
//        loopPlay=true;
//    }
}

void MainWindow::on_btnNext_clicked()
{//下一曲
    int count=ui->listWidget->count();
    int curRow=ui->listWidget->currentRow();
    curRow++;
    curRow= curRow>=count? count-1:curRow;
    ui->listWidget->setCurrentRow(curRow);

    loopPlay=false;     //暂时设置为false,防止do_stateChanged()里切换曲目
    player->setSource(getUrlFromItem(ui->listWidget->currentItem()));
    player->play();
    loopPlay=ui->btnLoop->isChecked();

//    if(ui->btnLoop->isChecked())
//    {
//        loopPlay=false;     //暂时设置为false,防止do_stateChanged()里切换曲目
//        player->setSource(getUrlFromItem(ui->listWidget->currentItem()));
//        player->play();
//        loopPlay=true;
//    }
}

这里切换曲目时要注意循环播放的问题。如果界面上的“循环”按钮是被选中的,那么 loopPlay 值为 true。如果直接重新设置播放源,播放器的状态会变为停止状态,那么 do_stateChanged()函数就会自动切换曲目,导致混乱。因此,程序里先把变量 loopPlay 设置为 false,避免do_stateChanged()函数切换曲目,重新设置曲目并开始播放后,再重新设置变量 loopPlay 的值。

QMediaPlayer 各信号的处理

切换播放文件时 player 会发射 sourceChanged()和 metaDataChanged()信号。

sourceChanged()信号对应的槽函数如下,主要用于更新界面label的显示

void MainWindow::do_sourceChanged(const QUrl &media)
{//播放的文件发生变化时的响应
    ui->labCurMedia->setText(media.fileName());
}

metaDataChanged()信号对应的槽函数如下:

void MainWindow::do_metaDataChanged()
{//元数据变化时执行,显示歌曲图片
    QMediaMetaData metaData=player->metaData();     //元数据对象
    QVariant  metaImg= metaData.value(QMediaMetaData::ThumbnailImage);  //获取ThumbnailImage元数据,无效
//    QVariant  metaImg= metaData.value(QMediaMetaData::CoverArtImage);  //获取 CoverArtImage 元数据,无效
    if (metaImg.isValid())
    {
        QImage img= metaImg.value<QImage>();        //QVariant转换为QImage
        QPixmap musicPixmp= QPixmap::fromImage(img);
        if (ui->scrollArea->width() <musicPixmp.width())
            ui->labPic->setPixmap(musicPixmp.scaledToWidth(ui->scrollArea->width()-30));
        else
            ui->labPic->setPixmap(musicPixmp);
    }
    else
        ui->labPic->clear();
}

当播放媒介的元数据发生变化时,就读取媒介元数据中的 QMediaMetaData::ThumbnailImage

键的数据,这是歌曲的内嵌图片,是 QImage 类型的,如果判断有效就使用QPixmap显示到Label中,这里需要判断一下显示区域是否足够,并进行相应的调整。

播放源时长和播放位置发生变化时,player 会发射 durationChanged()和 positionChanged()信号。

durationChanged()信号对应的槽函数如下:

void MainWindow::do_durationChanged(qint64 duration)
{//播放源时长变化时执行,更新进度显示,一般切换曲目时会触发
    ui->sliderPosition->setMaximum(duration);

    int   secs=duration/1000;  //秒
    int   mins=secs/60;        //分钟
    secs=secs % 60;            //余数秒
    durationTime=QString::asprintf("%d:%d",mins,secs);
    ui->labRatio->setText(positionTime+"/"+durationTime);
}

一般曲目发生更改时,播放源的时长会发生变化,在这个槽函数中重新设置了进度条

positionChanged()信号对应的槽函数如下:

void MainWindow::do_positionChanged(qint64 position)
{//播放位置变化时执行,更新进度显示
    if (ui->sliderPosition->isSliderDown())     //滑条正被鼠标拖动
        return;

    ui->sliderPosition->setSliderPosition(position);
    int   secs=position/1000;   //秒
    int   mins=secs/60;         //分钟
    secs=secs % 60;             //余数秒
    positionTime=QString::asprintf("%d:%d",mins,secs);
    ui->labRatio->setText(positionTime+"/"+durationTime);
}

这个槽函数主要是用于更新界面进度条显示的,以实时显示播放的进度。

播放器开始播放、暂停播放和停止播放时会发射 playbackStateChanged()信号,该信号对应的槽函数如下所示:

void MainWindow::do_stateChanged(QMediaPlayer::PlaybackState state)
{//播放器状态变化时执行,更新按钮状态,或播放下一曲
    ui->btnPlay->setEnabled(state!=QMediaPlayer::PlayingState);
    ui->btnPause->setEnabled(state==QMediaPlayer::PlayingState);
    ui->btnStop->setEnabled(state==QMediaPlayer::PlayingState);

    //播放完一曲后停止了,如果loopPlay为true,自动播放下一曲
    if (loopPlay && (state ==QMediaPlayer::StoppedState))
    {
        int count=ui->listWidget->count();
        int curRow=ui->listWidget->currentRow();
        curRow++;
        curRow= curRow>=count? 0:curRow;    //最后一曲播放完后切换到第一曲
        ui->listWidget->setCurrentRow(curRow);
        player->setSource(getUrlFromItem(ui->listWidget->currentItem()));
        player->play();
    }
}

MainWindow 类的私有变量 loopPlay 表示是否要循环播放,使用界面上的“循环”按钮可以 对应设置这个变量的值。QMediaPlayer 播放完当前曲目后就进入停止状态,不会自动播放下一曲。 为了实现循环播放,我们将界面组件 listWidget 的当前行下移或重设为 0,然后重新设置播放器的播放媒介并开始播放。

其他播放控制

界面下方的一些按钮和组件用于进行播放控制和设置,包括控制播放器开始播放、暂停播放和停止播放,设置播放倍速,设置是否循环播放,设置静音和音量,拖动播放进度条的滑块直接改变播放位置。对应的槽函数如下所示:

void MainWindow::on_btnPlay_clicked()
{//开始播放
    if (ui->listWidget->currentRow()<0)   //没有选择文件,就播放第1个
        ui->listWidget->setCurrentRow(0);
    player->setSource(getUrlFromItem(ui->listWidget->currentItem()));
    player->play();
    loopPlay=ui->btnLoop->isChecked();  //是否循环播放
}
void MainWindow::on_btnPause_clicked()
{//暂停播放
    player->pause();
}

void MainWindow::on_btnStop_clicked()
{//停止播放
    loopPlay=false;
    player->stop();
}

void MainWindow::on_sliderVolumn_valueChanged(int value)
{//调整音量
    player->audioOutput()->setVolume(value/100.0);        //0~ 1之间
}

void MainWindow::on_btnSound_clicked()
{//静音控制
    bool mute=player->audioOutput()->isMuted();
    player->audioOutput()->setMuted(!mute);
    if (mute)
        ui->btnSound->setIcon(QIcon(":/images/images/volumn.bmp"));
    else
        ui->btnSound->setIcon(QIcon(":/images/images/mute.bmp"));
}

void MainWindow::on_sliderPosition_valueChanged(int value)
{//播放进度调控
    player->setPosition(value);
}

void MainWindow::on_doubleSpinBox_valueChanged(double arg1)
{//"倍速" DoubleSpinbox
    player->setPlaybackRate(arg1);
}

QSoundEffect 播放音效文件

QSoundEffect 用于播放低延迟音效文件,例如无压缩的 WAV 文件,从而实现一些音效,例如按键音、提示音,游戏中的爆炸音、开枪音等。QSoundEffect 不仅可以播放本地文件,还可以播放网络文件。通常使用该类播放一些时长较短的音频。

示例代码如下:

#include "widget.h"
#include "ui_widget.h"

#include    <QPainter>
#include    <QPaintEvent>

void Widget::defense(QString weapon)
{
    QUrl   url=QUrl::fromLocalFile(appPath+"/sound/"+weapon);
    player1->setSource(url);
    player1->play();
}

void Widget::attack(QString weapon)
{
    QUrl   url=QUrl::fromLocalFile(appPath+"/sound/"+weapon);
    player2->setSource(url);
    player2->play();
}

void Widget::paintEvent(QPaintEvent *event)
{
	QPainter painter(this);
	painter.drawPixmap(0,0,this->width(), this->height(),pixBackground);
	event->accept();
}

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    appPath=QCoreApplication::applicationDirPath(); //  无“/”

    pixBackground.load(appPath+"/sound/background.jpg");

    player1=new QSoundEffect(this);
    player1->setLoopCount(3);

    player2=new QSoundEffect(this);
    player2->setLoopCount(3);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_clicked()
{
    defense("Ak7.wav");
}

void Widget::on_pushButton_2_clicked()
{
    defense("machinegun.wav");
}

void Widget::on_pushButton_5_clicked()
{
    attack("Ak7.wav");
}

void Widget::on_pushButton_6_clicked()
{
    attack("machinegun.wav");
}

void Widget::on_pushButton_8_clicked()
{
    attack("blast.wav");
}

void Widget::on_pushButton_12_clicked()
{
    attack("tank.wav");
}

void Widget::on_pushButton_11_clicked()
{
    attack("mine.wav");
}

void Widget::on_pushButton_9_clicked()
{
    defense("shell.wav");
}

void Widget::on_pushButton_4_clicked()
{
    defense("blast.wav");
}

void Widget::on_pushButton_10_clicked()
{
    defense("blast2.wav");
}

void Widget::on_pushButton_3_clicked()
{
     defense("fire.wav");
}

void Widget::on_pushButton_7_clicked()
{
    attack("fire2.wav");
}

参考

QT6 C++开发指南

标签:多媒体,QT,void,MainWindow,player,ui,listWidget,播放,音频
From: https://blog.csdn.net/qq_46144191/article/details/144577632

相关文章

  • Python创建图形用户界面(GUI):PyQt
    一、PyQt 简介定义PyQt 是一个用于创建图形用户界面(GUI)的 Python 库。它是 Qt 库的 Python 绑定,Qt 是一个跨平台的 C++ 库,广泛用于开发 GUI 应用程序、游戏开发、嵌入式系统等众多领域。PyQt 允许 Python 开发者利用 Qt 强大的功能来构建具有丰富交互性的......
  • 武理多媒体信息共享平台(源码+数据库+报告)
    360.基于SpringBoot的武理多媒体信息共享平台,系统包含两种角色:管理员、用户,系统分为前台和后台两大模块二、项目技术编程语言:Java数据库:MySQL项目管理工具:Maven前端技术:Vue后端技术:SpringBoot三、运行环境操作系统:Windows、macOS都可以JDK版本:JDK1.8以上都可以开发......
  • Pyqt6在lineEdit中输入文件名称并创建或删除JSON文件
    1、创建JSON文件代码importosdefaddModulekeyWordFile(self):if""!=self.lineEdit_module.text():moduleFile=self.lineEdit_module.text()+'.json'else:self.toolLogPrinting('请输入模块名称')returnfile......
  • QT网盘笔记(日志,qss,加密)
    前言:本章为本人在学习QT网盘时学到的知识,在此记录。一、QT日志1、前因(1)网盘服务端需要记录每一个登陆者登录的时间,账号名,在遇到除操作错误的错误时候会统计到日志中,同时客户的意见反馈也写入其中。(2)加上互斥锁防止多线程写入时混乱。2、互斥锁    (1)定义:在多......
  • Exif Pilot 是一款用于查看、编辑、创建和管理图像文件中 EXIF 数据的工具。EXIF(Excha
    ExifPilot是一款用于查看、编辑、创建和管理图像文件中EXIF数据的工具。EXIF(ExchangeableImageFileFormat)是照片、图像和其他多媒体文件中嵌入的元数据标准,通常包含图像拍摄时的相关信息,如拍摄日期、相机设置、GPS位置、分辨率、白平衡等。ExifPilot的功能查看EXIF......
  • 【Qt编程入门】
    目录【调试信息】【帮助文档】【项目结构】项目配置文件(.pro):用户文件(.user):主文件(main.cpp):头文件(.h):源文件(.cpp):【目录说明】构建目录:工作目录:【项目创建指南】特点:Qt在软件开发中的应用极为广泛:纯软件开发:Qt被广泛应用于开发各种桌面应用程序,如WPSOffice、暴......
  • pyqt5之GroupBox
    importsysfromPyQt5.QtWidgetsimportQApplication,QGroupBox,QVBoxLayout,QPushButton,QWidgetapp=QApplication(sys.argv)#创建一个QWidget作为主窗口main_widget=QWidget()#创建一个QGroupBoxgroupBox=QGroupBox("我的分组框")groupBox.setStyleS......
  • Android15音频进阶之车载AAOS系统open stream(九十九)
    简介:CSDN博客专家、《Android系统多媒体进阶实战》一书作者新书发布:《Android系统多媒体进阶实战》......
  • pyqt5文件对话框
    对话框选择文件#-*-coding:utf-8-*-#Formimplementationgeneratedfromreadinguifile'QFileDialog.ui'##Createdby:PyQt5UIcodegenerator5.15.9##WARNING:Anymanualchangesmadetothisfilewillbelostwhenpyuic5is#runagain.Do......
  • PyQt5与OpenCV结合的三个小练习
    题目1、简单图像处理创建一个PyQt应用程序,该应用程序能够:1、使用OpenCV加载一张图像。2、在PyQt的窗口中显示这张图像。3、提供四个按钮(QPushButton):一个用于将图像转换为灰度图一个用于将图像恢复为原始彩色图一个用于将图像进行翻转一个用于将图像进行旋转4、当用......