QT QMediaPlayer音频视频播放器

用QT做了一个简单的媒体播放器,UI比较粗糙但用起来还行。功能有基本的播放暂停功能,并支持拖拽。具体步骤如下。

首先建一个QT GUI程序,widget选MainWindow或者Widget都可以,我选的是MainWindow。

建好后在pro文件中添加以下语句,为了引用QT多媒体:

QT       += multimedia multimediawidgets

绘制GUI如下:

上方一个widget,由QVideoWidget的子类提升而来。下方是一个QSlider,用来显示播放进度。最下面是三个按钮,用来打开和播放。继承QVideoWidget,widget提升时候用到。videowidget.h。

#ifndef VIDEOWIDGET_H
#define VIDEOWIDGET_H
#include <QVideoWidget>

class VideoWidget : public QVideoWidget
{
    Q_OBJECT
public:
    VideoWidget(QWidget *parent = nullptr);
    ~VideoWidget();
};

#endif // VIDEOWIDGET_H

videowidget.cpp

#include "videowidget.h"
#include <QDebug>

VideoWidget::VideoWidget(QWidget *parent) :
    QVideoWidget (parent)
{
}

VideoWidget::~VideoWidget()
{

}

头文件mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include "videowidget.h"
#include <QFileDialog>
#include <QLabel>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void addToPlaylist(const QStringList &fileNames);

private slots:
    void openFile(QString filename = "");
    void playFile();
    void stopVideo();
    void positionChange(qint64 position);

protected:
    void dragEnterEvent(QDragEnterEvent *);
    void dropEvent(QDropEvent *);
    void wheelEvent(QWheelEvent *event);
    bool eventFilter(QObject *obj, QEvent *event);

private:
    Ui::MainWindow *ui;
    QMediaPlayer *m_player;
    QString m_fileName;
    QMediaPlaylist *m_playlist;
    QMediaPlayer::State m_playerState;
    bool b_moveSlider;
    QLabel *timeStatus;

};

#endif // MAINWINDOW_H

源文件videowidget.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtDebug>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QList>
#include <QMimeData>
#include <QTime>
#include <QWheelEvent>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowIcon(QIcon("://cd"));
    setAcceptDrops(true);

    m_player = new QMediaPlayer;
    m_playlist = new QMediaPlaylist;
    m_player->setPlaylist(m_playlist);

    m_player->setVideoOutput(ui->widget);

    b_moveSlider = false;
    //绑定信号槽
    connect(ui->bt_Open, SIGNAL(clicked()), this, SLOT(openFile()));
    connect(ui->bt_Play, SIGNAL(clicked()), this, SLOT(playFile()));
    connect(ui->bt_Stop, SIGNAL(clicked()), this, SLOT(stopVideo()));

    connect(m_player, SIGNAL(positionChanged(qint64)), this, SLOT(positionChange(qint64)));
    connect(m_player, &QMediaPlayer::mediaStatusChanged, this, [=] (QMediaPlayer::MediaStatus status) {
        if (status == QMediaPlayer::MediaStatus::EndOfMedia)
        {
            playFile();
        }
    });
    timeStatus = new QLabel(this);
    timeStatus->setFrameStyle(QFrame::Box|QFrame::Sunken);
    ui->statusBar->addPermanentWidget(timeStatus);
    ui->progressBar->installEventFilter(this);
}

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

void MainWindow::addToPlaylist(const QStringList &fileNames)
{
    foreach (QString const &name, fileNames)
    {
        QFileInfo fileInfo(name);
        if (fileInfo.exists())
        {
            QUrl url = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
            if (fileInfo.suffix().toLower() == "m3u")
            {
                m_playlist->load(url);
            }
            else
            {
                m_playlist->addMedia(url);
            }
        }
    }
}

void MainWindow::openFile(QString filename)
{
    QStringList fileNames;
    if (filename.length() > 0)
    {
        fileNames.append(filename);
    }
    else {
        fileNames = QFileDialog::getOpenFileNames(this, tr("Open Files"));
    }
    if (fileNames.length() <= 0)
    {
        return;
    }

    int index = m_playlist->currentIndex();
    if (index >= 0)
    {
        m_player->pause();
        m_playerState = QMediaPlayer::PausedState;
        m_playlist->removeMedia(index);
    }

    addToPlaylist(fileNames);

    playFile();
    positionChange(0);
    setWindowTitle(m_player->currentMedia().canonicalUrl().fileName());//在title处显示文件名
}

void MainWindow::playFile()
{
    if (m_player->playlist()->isEmpty())
    {
        return;
    }
    if (m_playerState != QMediaPlayer::PlayingState)
    {
        m_playerState = QMediaPlayer::PlayingState;
        m_player->play();
        ui->bt_Play->setText(tr("暂停"));
    }
    else
    {
        m_playerState = QMediaPlayer::PausedState;
        m_player->pause();
        ui->bt_Play->setText(tr("播放"));
    }

}

void MainWindow::stopVideo()
{
    m_playerState = QMediaPlayer::StoppedState;
    m_player->stop();
    ui->bt_Play->setText(tr("播放"));
    positionChange(0);
}
void MainWindow::positionChange(qint64 position)
{

    if(m_player->duration()/1000 != ui->progressBar->maximum())
    {
        ui->progressBar->setMaximum(static_cast<int>(m_player->duration()/1000));
    }
    ui->progressBar->setValue(static_cast<int>(position/1000));

    QTime initTime(0, 0, 0);
    QTime curtime = initTime.addMSecs(static_cast<int>(position));
    QTime totaltime = initTime.addMSecs(static_cast<int>(m_player->duration()));
    timeStatus->clear();
    timeStatus->setText(curtime.toString() + "/" +totaltime.toString());
}

void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    event->acceptProposedAction();
    QWidget::dragEnterEvent(event);
}

void MainWindow::dropEvent(QDropEvent *event)
{
    QList<QUrl> urls = event->mimeData()->urls();
    if (urls.isEmpty())
    {
        return;
    }
    openFile(urls.first().toLocalFile());
    QWidget::dropEvent(event);
}

void MainWindow::wheelEvent(QWheelEvent *event)
{
    QPoint numDegrees = event->angleDelta();
    int volume = m_player->volume();
    if (numDegrees.y() > 0)
    {
       volume++;
    }
    else
    {
        volume--;
    }
    m_player->setVolume(volume);
    QMainWindow::wheelEvent(event);
}

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == ui->progressBar)
    {
        if (event->type() == QEvent::MouseButtonRelease)
        {
            //获取当前鼠标位置
            int currentX = static_cast<QMouseEvent*>(event)->x();
            //计算当前位置占整个slider的百分比
            double percentage = currentX*1.0/ui->progressBar->width();
            //计算具体只
            int value = percentage*(ui->progressBar->maximum() - ui->progressBar->minimum()) + ui->progressBar->minimum();
            ui->progressBar->setValue(value);

            qDebug()<<ui->progressBar->value();
            qint64 newValue = ui->progressBar->value() * 1000;
            if (!m_player->currentMedia().isNull())
            {
                m_player->setPosition(newValue);
            }

        }
        else if (event->type() == QEvent::MouseButtonPress)
        {
            return true;
        }
    }
    return QMainWindow::eventFilter(obj, event);
}

直接获得媒体长度是0,需要用connect(m_player, SIGNAL(positionChanged(qint64)), this, SLOT(positionChange(qint64)));来获得positionChanged信号,才能得到媒体长度以及播放位置。

在用鼠标拖动slider更改播放位置时,如果移动鼠标到某个位置不放,会有播放位置来回跳动的问题。解决方法是移动鼠标时候断开positionChanged()信号,等放开鼠标后再连接。

2023.7.4:修正了鼠标设置播放位置不正确的问题,修正了播放结束状态不正确的问题。

QTgithub地址Q

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值