QT实现视频播放器(带进度条)

本篇文章介绍QT实现视频播放器的过程,视频播放器功能包括选择视频文件,播放暂停,显示视频播放时长和总时长,带进度条,并且进度条可拖动。

1.实现视频播放器,主要用到QMediaPlayer和QVideoWidget两个类。创建好工程后,在.pro文件中加入:QT += multimedia multimediawidgets

QT       += core gui multimedia multimediawidgets

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    premiere.cpp \
    sliderbar.cpp \

HEADERS += \
    premiere.h \
    sliderbar.h \

FORMS += \
    premiere.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

RESOURCES += \
    resource.qrc

2.这是我项目中的UI界面,btn_open是打开视频文件按钮,widget用来做视频输出窗口,progress是视频播放进度条,btn_play是播放暂停按钮,label用来显示视频播放时长和总时长。

 3.创建播放器 和视频输出对象。

.h文件中创建

private:
    Ui::Premiere *ui;
    QVideoWidget *videowidget;
    QMediaPlayer *player;

.cpp文件中设置

Premiere::Premiere(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Premiere)
{
    ui->setupUi(this);
    player = new QMediaPlayer(this);
    videowidget = new QVideoWidget(ui->widget);    //把ui中的widget设置为视频播放窗口
    QVBoxLayout *layout = new QVBoxLayout;    //设置布局
    layout->addWidget(videowidget);
    ui->widget->setLayout(layout);
}

如果视频文件打开后,视频没有显示出来,并且报错为:

DirectShowPlayerService::doRender: Unresolved error code 0x80040266 

说明没有视频解码器,可参考文章:

QT无法播放视频:报错:DirectShowPlayerService::doRender: Unresolved error code 0x80040266_泡泡上道了的博客-CSDN博客

下面展示项目中的所有代码,总共有4个文件,Premiere类的.h和.cpp文件实现视频播放器,SliderBar类的.h和.cpp文件实现进度条移动等。

Premiere.h

#ifndef PREMIERE_H
#define PREMIERE_H

#include <QWidget>
#include <QMediaPlayer>
#include <QVideoWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Premiere; }
QT_END_NAMESPACE

class Premiere : public QWidget
{
    Q_OBJECT

public:
    Premiere(QWidget *parent = nullptr);
    ~Premiere();
    void onPlayerPosition(qint64 pos);


private slots:
    void on_btn_open_clicked();

    void on_btn_play_clicked();

    void onMediaStatusChanged(QMediaPlayer::MediaStatus status);

    void updateTimes(qint64 position);


private:
    Ui::Premiere *ui;
    QVideoWidget *videowidget;
    QMediaPlayer *player;
    qint64 m_currentPosition;   //当前时长
    qint64 m_duration;        // 总时长

};
#endif // PREMIERE_H

Premiere.cpp文件

#include "premiere.h"
#include "ui_premiere.h"
#include "sliderbar.h"
#include <QMediaPlayer>
#include <QVideoWidget>
#include <QFileDialog>
#include <QDateTime>

Premiere::Premiere(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Premiere)
{
    ui->setupUi(this);
    player = new QMediaPlayer(this);
    videowidget = new QVideoWidget(ui->widget);
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(videowidget);
    ui->widget->setLayout(layout);


    ui->progress->setEnabled(false);


    connect(player, &QMediaPlayer::mediaStatusChanged, this, &Premiere::onMediaStatusChanged);
    //视频播放进度条
    connect(player,&QMediaPlayer::positionChanged,ui->progress,&SliderBar::setValue);
    connect(player,&QMediaPlayer::durationChanged,ui->progress,&SliderBar::setDurationPosition);
    connect(ui->progress,&SliderBar::sigProgress,this,&Premiere::onPlayerPosition);
    //显示视频播放时长
    connect(player,&QMediaPlayer::positionChanged,this,&Premiere::updateTimes);
    connect(player,&QMediaPlayer::durationChanged,this,&Premiere::updateTimes);

}

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

/**
 * @brief Premiere::on_progress_valueChanged
 * @param value
 * @caption 视频播放进度条
 */
void Premiere::onPlayerPosition(qint64 pos)
{
    disconnect(player,&QMediaPlayer::positionChanged,ui->progress,&SliderBar::setValue);
    player->setPosition(pos);
    m_currentPosition = pos;    //更新当前播放位置
    connect(player,&QMediaPlayer::positionChanged,ui->progress,&SliderBar::setValue);

}


/**
 * @brief Premiere::on_btn_open_clicked
 * @caption 打开视频文件按钮
 */
void Premiere::on_btn_open_clicked()
{
    //获取视频文件路径
    QString videoFilePath = QFileDialog::getOpenFileName(this, "选择视频文件", QDir::homePath(), "视频文件 (*.mp4 *.avi)");


    // 将 QVideoWidget 设置为 QMediaPlayer 的输出设备
    player->setVideoOutput(videowidget);
    // 加载视频文件
    player->setMedia(QUrl::fromLocalFile(videoFilePath));   
    // 播放视频
    player->pause();

    ui->progress->setEnabled(true);

}


/**
 * @brief Premiere::on_btn_play_clicked
 * @caption 播放暂停按钮
 */
void Premiere::on_btn_play_clicked()
{
    if(player->state()==QMediaPlayer::PlayingState)
    {
        //当前正在播放,点击按钮暂停
        player->pause();
        ui->btn_play->setIcon(QIcon(":/resource/play.png"));
    }
    else
    {
        //当前处于暂停状态,点击按钮播放
        player->play();
        ui->btn_play->setIcon(QIcon(":/resource/stop.png"));

    }
}




void Premiere::onMediaStatusChanged(QMediaPlayer::MediaStatus status)
{
    if (status == QMediaPlayer::EndOfMedia)
    {
        // 视频播放完毕,将按钮状态设置为暂停状态
        ui->btn_play->setIcon(QIcon(":/resource/play.png"));
        player->setPosition(0);
    }
}


/**
 * @brief Premiere::updateTimes
 * @param position
 * @caption 设置视频当前时长和总时长
 */
void Premiere::updateTimes(qint64 position)
{
    m_currentPosition = position;
    QTime currentTime(0,0,0);
    currentTime = currentTime.addMSecs(position);

    m_duration = player->duration();
    QTime totalTime(0,0,0);
    totalTime = totalTime.addMSecs(m_duration);

    QString currentTimeString = currentTime.toString("hh:mm:ss");
    QString totalTimeString = totalTime.toString("hh:mm:ss");

    ui->label->setText(currentTimeString+"/"+totalTimeString);

}

SliderBar.h

这个类的作用有3个:1)接收QMediaPlaer发来的进度信息,更新进度条;2)当用户操作进度条时,不再让进度条响应QMediaPlaer发来的进度信息;3)当用户完成对进度条的拖动后,向QMediaPlaer发送播放位置更新信息。

这个类的实现参考了文章:qt实现视频播放器_setvideooutput(m_pplayerwidget)_金色熊族的博客-CSDN博客

#ifndef SLIDERBAR_H
#define SLIDERBAR_H

#include <QSlider>
#include <QMouseEvent>

class SliderBar : public QSlider
{
    Q_OBJECT
public:
    SliderBar(QWidget *parent = 0);

public slots:
    void setDurationPosition(qint64 max_len);

signals:
    void sigProgress(qint64 pos);

protected:
    void mouseReleaseEvent(QMouseEvent *e);
    void mousePressEvent(QMouseEvent *e);
    void mouseMoveEvent(QMouseEvent *e);



};

#endif // SLIDERBAR_H

SliderBar.cpp

#include "sliderbar.h"

SliderBar::SliderBar(QWidget *parent):QSlider(parent)
{

}

void SliderBar::setDurationPosition(qint64 max_len)
{
    setRange(0,max_len);
}


void SliderBar::mouseReleaseEvent(QMouseEvent *e)
{
    qint64 pos = this->value();
    emit sigProgress(pos);
    QSlider::mouseReleaseEvent(e);
}

void SliderBar::mousePressEvent(QMouseEvent *e)
{
    QSlider::mousePressEvent(e);
}

void SliderBar::mouseMoveEvent(QMouseEvent *e)
{
    QSlider::mouseMoveEvent(e);
}

效果展示:进度条可拖动

猜你喜欢

转载自blog.csdn.net/weixin_55735677/article/details/131247801