目录
一.播放器设计
二.需要使用的控件
三.选择视频
四.播放视频
五.暂停视频
六.关闭视频
七.播放状态设置
八.切换视频(上一首)
九.切换视频(下一首)
十.设置视频滑块
十一.更新滑块显示
十二.实现效果
十三.代码设计
1.mainwindow.h
2.mainwindow.cpp
一.播放器设计
播放器主要包含了媒体播放器的基本功能,如选择视频,播放、停止、快进、快退、播放列表管理、时间显示、状态指示等。
mainwindow.ui
二.需要使用的控件
QSlider是一个用于用户输入的控件,主要用于实现滑动条功能。滑动条允许用户通过滑动滑块在一组连续的值中选择一个值。QSlider通常用于控制数值的调整,如音量、亮度、滚动条等。
QLabel是一个用于显示文本或者图像的控件。它是Qt框架中用于界面布局和显示信息的基本组件之一。QLabel可以用来显示各种类型的信息,如文本、图片、图标等。
QListView是一个用于显示和浏览项目列表的视图控件。它通常与QModel(如QAbstractListModel或QStandardItemModel)一起使用来管理数据,并允许用户通过滚动和点击来浏览这些数据。
QPushButton是一个常用的标准控件,用于创建按钮,用户可以通过点击按钮来触发事件。QPushButton可以显示文本、图标或者两者的组合。
三.选择视频
- 打开一个文件对话框,让用户选择一个或多个视频文件。
- 如果用户选择了文件,则将文件路径添加到一个QStringList对象中。
- 遍历这些文件路径,并将每个文件的名称添加到一个QStandardItemModel(假设名为
model
)中。 - 设置一个多媒体播放器(假设名为
player
)的媒体内容为第一个文件的内容,准备播放。
四.播放视频
五.暂停视频
六.关闭视频
七.播放状态设置
八.切换视频(上一首)
-
获取和检查索引:首先获取当前在列表视图中选中的项目的索引,然后检查这个索引是否有效。如果有效,说明用户已经选中了一个项目。
-
处理有效索引:如果当前索引有效,代码将计算前一个项目的索引,并确保这个索引在列表范围内循环,即使当前处于第一项也能回到最后一项。然后,它将这个前一个项目设置为列表视图的当前选中项,并获取该项对应的媒体文件路径,最后通过媒体播放器对象播放这个媒体文件。
-
处理无效索引:如果当前索引无效,即没有选中任何项目,代码将自动选择列表中的最后一项,并播放与该项对应的媒体文件。这确保了即使在没有任何选中项的情况下,用户也能通过播放列表的最后一项来开始播放。
九.切换视频(下一首)
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_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic: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();}}
}