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

QT:音视频播放器

目录

一.播放器设计

二.需要使用的控件

三.选择视频

四.播放视频

五.暂停视频

六.关闭视频

七.播放状态设置

八.切换视频(上一首)

九.切换视频(下一首)

十.设置视频滑块

十一.更新滑块显示

十二.实现效果

十三.代码设计

1.mainwindow.h

2.mainwindow.cpp


一.播放器设计

播放器主要包含了媒体播放器的基本功能,如选择视频,播放、停止、快进、快退、播放列表管理、时间显示、状态指示等。

mainwindow.ui

二.需要使用的控件

QSlider是一个用于用户输入的控件,主要用于实现滑动条功能。滑动条允许用户通过滑动滑块在一组连续的值中选择一个值。QSlider通常用于控制数值的调整,如音量、亮度、滚动条等。

QLabel是一个用于显示文本或者图像的控件。它是Qt框架中用于界面布局和显示信息的基本组件之一。QLabel可以用来显示各种类型的信息,如文本、图片、图标等。

QListView是一个用于显示和浏览项目列表的视图控件。它通常与QModel(如QAbstractListModel或QStandardItemModel)一起使用来管理数据,并允许用户通过滚动和点击来浏览这些数据。

QPushButton是一个常用的标准控件,用于创建按钮,用户可以通过点击按钮来触发事件。QPushButton可以显示文本、图标或者两者的组合。

三.选择视频

  1. 打开一个文件对话框,让用户选择一个或多个视频文件。
  2. 如果用户选择了文件,则将文件路径添加到一个QStringList对象中。
  3. 遍历这些文件路径,并将每个文件的名称添加到一个QStandardItemModel(假设名为model)中。
  4. 设置一个多媒体播放器(假设名为player)的媒体内容为第一个文件的内容,准备播放。

四.播放视频

五.暂停视频

六.关闭视频

七.播放状态设置

八.切换视频(上一首)

  1. 获取和检查索引:首先获取当前在列表视图中选中的项目的索引,然后检查这个索引是否有效。如果有效,说明用户已经选中了一个项目。

  2. 处理有效索引:如果当前索引有效,代码将计算前一个项目的索引,并确保这个索引在列表范围内循环,即使当前处于第一项也能回到最后一项。然后,它将这个前一个项目设置为列表视图的当前选中项,并获取该项对应的媒体文件路径,最后通过媒体播放器对象播放这个媒体文件。

  3. 处理无效索引:如果当前索引无效,即没有选中任何项目,代码将自动选择列表中的最后一项,并播放与该项对应的媒体文件。这确保了即使在没有任何选中项的情况下,用户也能通过播放列表的最后一项来开始播放。

九.切换视频(下一首)

1.当用户点击“下一项”按钮时被调用。它首先获取当前选中的列表项索引,如果索引有效,则获取下一项的索引,如果下一项索引无效(即已经是最后一项),则跳转到列表的第一项。

2.将列表视图的当前索引设置为新的索引,并播放与该索引对应的媒体文件。如果当前索引无效(即列表为空或没有选中任何项),它将选择并播放列表的第一项。

十.设置视频滑块

十一.更新滑块显示

1.更新滑块显示

2.计算已经观看时间和剩余时间

3.格式化时间

4.更新已观看时间和剩余时间都标签

十二.实现效果

十三.代码设计

1.mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDialog>
#include <QWidget>
#include <QMediaPlayer>
#include <QVideoWidget>
#include <QPushButton>
#include <QLineEdit>
#include <QFileDialog>
#include <QUrl>
#include <QListView>
#include <QStandardItem>
#include <QStandardItemModel>


QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_play_clicked();

    void on_stop_clicked();

    void on_pushButton_clicked();

    void on_close_clicked();

    void on_horizontalSlider_actionTriggered(int position);

    void on_listView_doubleClicked(const QModelIndex &index);

    void updatePosition(qint64 position);
    void labelstateChanged(QMediaPlayer::State state);

    QString formatTime(int seconds);

    void on_previous_clicked();

    void on_next_clicked();

private:
    QMediaPlayer *player;
    QVideoWidget *videoWidget;
    QString videoPath;

    QStandardItemModel *model; // 声明 model 变量

    Ui::MainWindow *ui;

};
#endif // MAINWINDOW_H

2.mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMediaPlayer>
#include <QVideoWidget>
#include <QDebug>

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

    player = new QMediaPlayer(this);
    videoWidget = new QVideoWidget(this);

    // 设置视频输出
    player->setVideoOutput(videoWidget);


    connect(player, &QMediaPlayer::positionChanged,this, &MainWindow::updatePosition);
    connect(player, &QMediaPlayer::stateChanged,this,&MainWindow::labelstateChanged);
    connect(ui->listView, &QListView::doubleClicked, this, &MainWindow::on_listView_doubleClicked);

    connect(ui->horizontalSlider, &QSlider::valueChanged, this, &MainWindow::on_horizontalSlider_actionTriggered);

    // 初始化模型
    model = new QStandardItemModel(this);
    ui->listView->setModel(model); // 设置 listView 的模型

    videoWidget->move(QPoint(10, 50));

    // 设置视频Widget的尺寸
    videoWidget->resize(280, 280);
}

MainWindow::~MainWindow()
{
    delete ui;
    // 这里确保删除player和videoWidget以避免内存泄露
    delete player;
    delete videoWidget;
}

void MainWindow::on_play_clicked()
{
   player->play();
}

void MainWindow::on_stop_clicked()
{
    player->pause();
}

void MainWindow::on_pushButton_clicked()
{
    
    // 使用QFileDialog获取文件路径列表
    QStringList filePaths = QFileDialog::getOpenFileNames(this, tr("选择视频文件"), ""/*, tr("MP4 Files (*.mp4);;All Files (*)")*/);
    
    // 检查是否选择了文件
    if (!filePaths.isEmpty()) {
        // 遍历所有选中的文件路径
        for (const QString &filePath : filePaths) {
            // 创建一个新的QStandardItem,包含文件名
            QStandardItem *item = new QStandardItem(QFileInfo(filePath).fileName());
            
            // 将该项添加到模型中,这里假设model是QStandardItemModel的实例
            model->appendRow(item); // 将视频文件名称添加到模型中
        }
        
        // 设置播放器的媒体内容为第一个文件的内容,准备播放
        player->setMedia(QMediaContent(QUrl::fromLocalFile(filePaths.first())));
    }

}

void MainWindow::on_close_clicked()
{
    player->stop();
}

void MainWindow::on_horizontalSlider_actionTriggered(int position)
{
    player->setPosition(position * 1000);
}


void MainWindow::on_listView_doubleClicked(const QModelIndex &index)
{

    if (index.isValid()) {
        QStandardItem *item = model->itemFromIndex(index);
        if (item) {
            // 获取列表中当前选中项的文件路径
            QString filePath =  "E:/lzy/MediaPlayer/Test/" + item->text();  //videoPath;
            // 检查文件是否存在
            if (QFile::exists(filePath)) {
                player->setMedia(QMediaContent(QUrl::fromLocalFile(filePath)));
                player->play();
            } else {
                qDebug() << "File does not exist: " << filePath;
            }
        }
    }
}


void MainWindow::updatePosition(qint64 position)
{ // 更新滑块显示
     ui->horizontalSlider->setMaximum(player->duration() / 1000);
    // ui->horizontalSlider->setValue(position / 1000);


    // 计算已观看时间和剩余时间
    int currentSeconds = position / 1000;
    int totalSeconds = player->duration() / 1000;
    int remainingSeconds = totalSeconds - currentSeconds;

    // 格式化时间
    QString currentTimeStr = formatTime(currentSeconds);
    QString remainingTimeStr = formatTime(remainingSeconds);
    QString totalSecondsStr = formatTime(totalSeconds);

    // 更新已观看时间和剩余时间的标签
    ui->labelCurrentTime->setText(currentTimeStr);
    ui->labelRemainingTime->setText(remainingTimeStr);
    ui->labeltotalTime->setText(totalSecondsStr);

}

QString MainWindow::formatTime(int seconds)
{
    int minutes = seconds / 60;
    int secs = seconds % 60;
    return QString("%1:%2").arg(minutes, 2, 10, QChar('0')).arg(secs, 2, 10, QChar('0'));
}


void MainWindow::labelstateChanged(QMediaPlayer::State state)
{
    switch (state) {
    case QMediaPlayer::StoppedState:
        ui->labelstate->setText(tr("停止状态!"));
        break;
    case QMediaPlayer::PlayingState:
        ui->labelstate->setText(tr("播放状态!"));
        break;
    case QMediaPlayer::PausedState:
        ui->labelstate->setText(tr("暂停状态!"));
        break;
    default: break;
    }
}

void MainWindow::on_previous_clicked()
{
    // 获取当前选中的索引
    QModelIndex currentIndex = ui->listView->currentIndex();
    // 检查当前索引是否有效
    if (currentIndex.isValid()) {
        // 获取当前选中项的上一项的索引
        int currentRow = currentIndex.row();
        int previousRow = (currentRow - 1 + model->rowCount()) % model->rowCount(); // 使用模运算确保索引循环
        QModelIndex previousIndex = model->index(previousRow, currentIndex.column());
        // 选择上一项
        ui->listView->setCurrentIndex(previousIndex);
        // 播放上一项
        QStandardItem *previousItem = model->itemFromIndex(previousIndex);
        if (previousItem) {
            // 设置媒体内容为上一项的视频路径
            QString filePath = "E:/lzy/MediaPlayer/Test/" + previousItem->text(); // 假设文件路径是这样设置的
            player->setMedia(QMediaContent(QUrl::fromLocalFile(filePath)));
            player->play();
        }
    } else {
        // 如果当前索引无效,可能是没有选中任何项目,可以选择最后一项
        QModelIndex lastIndex = model->index(model->rowCount() - 1, 0);
        ui->listView->setCurrentIndex(lastIndex);
        // 播放最后一项
        QStandardItem *lastItem = model->itemFromIndex(lastIndex);
        if (lastItem) {
            QString filePath = "E:/lzy/MediaPlayer/Test/" + lastItem->text(); // 假设文件路径是这样设置的
            player->setMedia(QMediaContent(QUrl::fromLocalFile(filePath)));
            player->play();
        }
    }
}

void MainWindow::on_next_clicked()
{
    // 获取当前选中的索引
    QModelIndex currentIndex = ui->listView->currentIndex();

    // 检查当前索引是否有效
    if (currentIndex.isValid()) {
        // 获取当前选中项的下一项的索引
        QModelIndex nextIndex = model->index(currentIndex.row() + 1, currentIndex.column());

        // 如果下一项索引无效,则跳转到最后一项
        if (!nextIndex.isValid()) {
            nextIndex = model->index(0, 0);
        }

        // 选择下一项
        ui->listView->setCurrentIndex(nextIndex);

        // 播放下一项
        QStandardItem *nextItem = model->itemFromIndex(nextIndex);
        if (nextItem) {
            // 设置媒体内容为下一项的视频路径
            QString filePath = "E:/lzy/MediaPlayer/Test/" + nextItem->text(); // 假设文件路径是这样设置的
            player->setMedia(QMediaContent(QUrl::fromLocalFile(filePath)));
            player->play();
        }
    } else {
        // 如果当前索引无效,可能是没有选中任何项目,可以选择第一项
        QModelIndex firstIndex = model->index(0, 0);
        ui->listView->setCurrentIndex(firstIndex);

        // 播放第一项
        QStandardItem *firstItem = model->itemFromIndex(firstIndex);
        if (firstItem) {
            QString filePath = "E:/lzy/MediaPlayer/Test/" + firstItem->text(); // 假设文件路径是这样设置的
            player->setMedia(QMediaContent(QUrl::fromLocalFile(filePath)));
            player->play();
        }
    }
}


http://www.kler.cn/a/304556.html

相关文章:

  • git没有识别出大写字母改成小写重命名的文件目录
  • 蓝桥杯c++算法学习【2】之搜索与查找(九宫格、穿越雷区、迷宫与陷阱、扫地机器人:::非常典型的必刷例题!!!)
  • WordPress 6.7 “Rollins”发布
  • androidstudio下载gradle慢
  • Ceph 中Crush 算法的理解
  • ubuntu20.04 解决Pytorch默认安装CPU版本的问题
  • 使用Python自动抓取亚马逊网站商品信息
  • 1. 运动控制指令概要(omron 机器自动化控制器)
  • 【MySQL】数据库的操作【字符集和校验规则】【对数据库进行操作】【数据库备份与恢复】
  • Axure多人协调的方式
  • c++207 运算重载
  • 【从问题中去学习k8s】k8s中的常见面试题(夯实理论基础)(二十八)
  • 【AWDP】 AWDP 赛制详解应对方法赛题实践 量大管饱
  • 2.大语言模型LLM的涌现能力和关键技术
  • 计算机网络 --- 【2】计算机网络的组成、功能
  • TDengine在设备管理系统中应用
  • 【拥抱AI】沉浸式体验SpaCy开源分词器
  • 摩托车加装车载手机充电usb方案/雅马哈USB充电方案开发
  • JVM基础:深入理解类加载器
  • Ubuntu22.04系统安装opencv步骤简述及问题解决方法
  • JavaScript 基础 - 第17天_AJAX综合案例
  • Android 开发入门教程-入门基础
  • 华为云ROMA Connect聚焦创新,在Gartner®峰会发布智能集成新视角
  • Linux的内存管理
  • Proxyless Service Mesh:下一代微服务架构体系
  • OpenHarmony(鸿蒙南向开发)——轻量和小型系统三方库移植指南(一)