QT项目实战(视频播放器)

news2024/12/28 3:40:02

文章目录

  • 前言
  • 一、QMediaPlayer
  • 二、QVideoWidget
  • 三、QAudioOutput
  • 四、播放器代码实现
  • 五、最终效果
  • 总结


前言

本篇文章将使用QT6.4来实现一个简单视频播放器,在QT中使用一个视频播放器还是非常简单的。那么下面就让我们一起来实现这个视频播放器吧。

一、QMediaPlayer

QMediaPlayer是Qt多媒体框架中的一个组件,它可以用于播放音频和视频文件。它使用了跨平台的Qt音频和视频后端,并兼容多种音频和视频格式,包括:MP3、WAV、OGG、AAC等音频格式,以及MPEG、AVI等视频格式。

使用QMediaPlayer需要先创建一个QMediaPlayer对象,然后调用setSource()函数来指定要播放的媒体文件。在调用play()函数后,QMediaPlayer对象会自动开始播放所指定的媒体文件。您还可以使用pause()函数和stop()函数来暂停和停止媒体播放。

QMediaPlayer还提供了一系列的信号和槽函数,使得用户可以在媒体播放期间捕获和处理多种事件,例如:播放出错、播放结束、媒体信息更新、媒体状态改变等等。使用这些信号和槽函数可以实现一些有趣和有用的功能,例如:精确控制播放进度、动态显示媒体元数据、同时播放多个媒体文件等等。

在使用这个类时需要在.pro文件中加上QT += multimedia
在这里插入图片描述

二、QVideoWidget

QVideoWidget是Qt框架中的组件之一,它提供了一个用于显示视频的自定义窗口。您可以将QVideoWidget添加到应用程序的用户界面中,然后使用QMediaPlayer或其他支持Qt视频框架的组件将视频播放到该窗口中。

使用QVideoWidget,您可以轻松实现视频播放器的自定义UI,例如:显示视频标题和长度、调整播放音量、显示屏幕截图和元数据等。QVideoWidget还可以处理一些常见的视频操作,例如全屏模式、视频缩放和窗口大小更改。

三、QAudioOutput

QAudioOutput是Qt框架中的一个组件,可用于播放音频数据。它使用了跨平台的Qt音频后端,并兼容多种音频格式,包括:WAV、MP3、AAC和OGG等。可以使用QAudioOutput将音频数据播放到扬声器或其他音频设备中,并可以控制播放进度、音量和状态等属性。

四、播放器代码实现

注释已经将重点部分都写出来了,这里我就不多介绍了。

widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QMediaPlayer>
#include <QVideoWidget>
#include <QAudioOutput>
#include <QPushButton>
#include <QSlider>
#include <QHBoxLayout>
#include <QLabel>
#include <QTime>

class Widget : public QWidget
{
    Q_OBJECT

    QMediaPlayer* player;
    QVideoWidget* videoWidget;
    QAudioOutput* audiooutput;

    QPushButton* m_voicebutton;
    QSlider* m_voiceslider;

    QPushButton* m_speedbutton;
    QLabel* m_speedlabel;
    QSlider* m_speedslider;

    QSlider* m_Progressslider;

    QPushButton* m_palybutton;
    QPushButton* m_stopbutton;
    QPushButton* m_backbutton;
    QPushButton* m_aheadbutton;
    QPushButton* m_selectbutton;
    QPushButton* m_fullscreen;

    QLabel* m_timelabel;

    QHBoxLayout* hlayout;

    QString m_resource;

    int m_voice;

    QString totalFormattedTime;
    QString currentFormattedTime;

    void Init();

    void ButtonStyleSet(QPushButton* button, QString IconPath);

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

protected slots:
    void voiceclick();
    void voicechange(int voice);
    void playclick();
    void stopclick();
    void getduration(qint64 duration);
    void VideoPosChange(qint64 position);
    void ProgressChange(int pos);
    void aheadclick();
    void backclick();
    void GetPlayResource();
    void SpeedChange(int value);
};
#endif // WIDGET_H

widget.cpp:

#include "widget.h"
#include <QVBoxLayout>
#include <QIcon>
#include <QDebug>
#include <QHBoxLayout>
#include <QPalette>


Widget::Widget(QWidget *parent): QWidget(parent), m_voice(50),
    currentFormattedTime("00:00")
{
    audiooutput = new QAudioOutput();

    QVBoxLayout* vlayout = new QVBoxLayout(this);
    hlayout = new QHBoxLayout();

    player = new QMediaPlayer;
    player->setPlaybackRate(1.0);//默认1倍速播放

    videoWidget = new QVideoWidget(this);
    videoWidget->setAspectRatioMode(Qt::IgnoreAspectRatio);//缩放适应videoWidget的大小

    player->setVideoOutput(videoWidget);//设置播放窗口
    player->setAudioOutput(audiooutput);//设置声音
    audiooutput->setVolume(m_voice);//初始音量为50

    Init();//UI控件初始化

    vlayout->addWidget(videoWidget, 8);
    vlayout->addWidget(m_Progressslider, 1);
    vlayout->addLayout(hlayout, 0);

    connect(player, SIGNAL(durationChanged(qint64)), this, SLOT(getduration(qint64)));
    connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(VideoPosChange(qint64)));

    videoWidget->show();//显示视频界面

    setFixedSize(1024, 600);
}

void Widget::ButtonStyleSet(QPushButton* button, QString IconPath)
{
    // 设置图像
    button->setIcon(QIcon(IconPath));
    button->setFlat(true);//去除边框
    button->setStyleSheet("QPushButton:hover {background-color: grey;} QPushButton:pressed {background-color: darkGrey;}");
}

void Widget::Init()
{
    /*声音控件*/
    m_voicebutton = new QPushButton();
    ButtonStyleSet(m_voicebutton, ":/voice.png");
    m_voiceslider = new QSlider(Qt::Horizontal);
    m_voiceslider->setValue(50);
    m_voiceslider->setRange(0, 100);

    /*倍速控件*/
    m_speedbutton = new QPushButton();
    ButtonStyleSet(m_speedbutton, ":/speed.png");
    m_speedlabel = new QLabel();
    m_speedslider = new QSlider(Qt::Horizontal);
    m_speedslider->setRange(0, 8);//0-4倍速
    m_speedslider->setTickInterval(1);
    m_speedslider->setValue(4);
    m_speedlabel->setText(QString::number(4.0 * 2.0 / 8.0, 'g', 3) + QString("倍速"));

    /*控制视频播放按键*/
    m_palybutton = new QPushButton();
    ButtonStyleSet(m_palybutton, ":/play.png");
    m_stopbutton = new QPushButton();
    ButtonStyleSet(m_stopbutton, ":/stop.png");
    m_backbutton = new QPushButton();
    ButtonStyleSet(m_backbutton, ":/back.png");
    m_aheadbutton = new QPushButton();
    ButtonStyleSet(m_aheadbutton, ":/ahead.png");
    m_fullscreen = new QPushButton();
    ButtonStyleSet(m_fullscreen, ":/Fullscreen.png");
    m_selectbutton = new QPushButton();
    ButtonStyleSet(m_selectbutton, ":/select.png");

    /*视频进度条*/
    m_Progressslider = new QSlider(Qt::Horizontal);
    m_Progressslider->setRange(0, 100);//设置进度条范围
    m_Progressslider->setValue(0);//初始值为0

    /*显示时间label*/
    m_timelabel = new QLabel();

    hlayout->addWidget(m_voicebutton);
    hlayout->addWidget(m_voiceslider);
    hlayout->addStretch();
    hlayout->addWidget(m_speedbutton);
    hlayout->addWidget(m_speedslider);
    hlayout->addWidget(m_speedlabel);
    hlayout->addStretch();
    hlayout->addWidget(m_palybutton);
    hlayout->addWidget(m_stopbutton);
    hlayout->addWidget(m_backbutton);
    hlayout->addWidget(m_aheadbutton);
    hlayout->addWidget(m_selectbutton);
    hlayout->addWidget(m_fullscreen);
    hlayout->addWidget(m_timelabel);


    connect(m_voicebutton, SIGNAL(clicked()), this, SLOT(voiceclick()));
    connect(m_voiceslider, SIGNAL(valueChanged(int)), this, SLOT(voicechange(int)));
    connect(m_palybutton, SIGNAL(clicked()), this, SLOT(playclick()));
    connect(m_stopbutton, SIGNAL(clicked()), this, SLOT(stopclick()));
    connect(m_Progressslider, SIGNAL(valueChanged(int)), this, SLOT(ProgressChange(int)));
    connect(m_aheadbutton, SIGNAL(clicked()), this, SLOT(aheadclick()));
    connect(m_backbutton, SIGNAL(clicked()), this, SLOT(backclick()));
    connect(m_selectbutton, SIGNAL(clicked()), this, SLOT(GetPlayResource()));
    connect(m_speedslider, SIGNAL(valueChanged(int)), this, SLOT(SpeedChange(int)));
}

Widget::~Widget()
{
}


videoslot.cpp:

#include "widget.h"
#include <QDebug>
#include <QIcon>
#include <QFile>
#include <QFileDialog>

void Widget::voiceclick()
{
    static int i = 0;
    i = !i;
    if(i == 1)
    {
        audiooutput->setVolume(0);//静音
        ButtonStyleSet(m_voicebutton, ":/novoice.png");
    }
    else if(i == 0)
    {
        audiooutput->setVolume(m_voice);//设置回到之前的音量
        ButtonStyleSet(m_voicebutton, ":/voice.png");
    }

}

void Widget::voicechange(int voice)
{
    audiooutput->setVolume(voice);
    if(voice == 0)
    {
        ButtonStyleSet(m_voicebutton, ":/novoice.png");
    }
    else
    {
        ButtonStyleSet(m_voicebutton, ":/voice.png");
    }
}

/*继续播放*/
void Widget::playclick()
{
    player->play();
}

/*暂停视频播放*/
void Widget::stopclick()
{
    player->pause();
}

void Widget::ProgressChange(int pos)
{
    if(m_Progressslider->isSliderDown())
    {
        player->setPosition(pos * player->duration() / 100);
    }
}

/*获得视频播放总时间*/
void Widget::getduration(qint64 duration)
{
    QTime totalTime = QTime(0, 0, 0, 0);
    totalTime = totalTime.addMSecs(duration); // 将视频的总时长(毫秒)添加到 QTime 对象中
    totalFormattedTime = totalTime.toString("mm:ss"); // 转换 QTime 对象到分:秒格式字符串
    m_timelabel->setText(currentFormattedTime + " / " + totalFormattedTime);
}

/*按下按键在当前的基础上前进10s*/
void Widget::aheadclick()
{
    qint64 currentpos = player->position();
    player->setPosition(currentpos + 10000);//在原来的基础上前进10s
}

/*按下按键在当前的基础上后退10s*/
void Widget::backclick()
{
    qint64 currentpos = player->position();
    player->setPosition(currentpos - 10000);//在原来的基础上前进10s
}

/*当视频播放时进度条改变调用此函数*/
void Widget::VideoPosChange(qint64 position)
{
    if(m_Progressslider->isSliderDown())
    {
        // 如果正在手动滑动条,则直接退出
        return;
    }
    m_Progressslider->setSliderPosition(100 * position / player->duration());

    QTime currentTime(0, 0, 0, 0); // 初始化一个时间为0的QTime对象
    currentTime = currentTime.addMSecs(player->position()); // 将当前播放时间(毫秒)添加到 QTime 对象中
    currentFormattedTime = currentTime.toString("mm:ss"); // 转换 QTime 对象到分:秒格式字符串
    m_timelabel->setText(currentFormattedTime + " / " + totalFormattedTime);
}

/*获得选择的播放源路径并播放*/
void Widget::GetPlayResource()
{
    m_resource = QFileDialog::getOpenFileName(this, tr("选择播放源"), "D:/VIdeo", tr("MP4 Files(*.mp4)"));
    player->setSource(QUrl::fromLocalFile(m_resource));//设置播放资源
    player->play();//播放视频
}

/*倍速设置*/
void Widget::SpeedChange(int value)
{
    m_speedlabel->setText(QString::number(value * 2.0 / 8.0, 'g', 3) + QString("倍速"));
    player->setPlaybackRate(value * 2.0 / 8.0);//设置倍速播放
}

五、最终效果

在这里插入图片描述

总结

源代码整理好后将放入微信公众号中,回复10即可领取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/605959.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习应用篇-计算机视觉-图像增广[1]:数据增广、图像混叠、图像剪裁类变化类等详解

【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、序列模型、预训练模型、对抗神经网络等 专栏详细介绍&#xff1a;【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化…

基于VGG16实现宝石图像分类任务(acc 84%)--paddle paddle

作业&#xff1a;补充网络定义部分&#xff0c;使用卷积神经网络实现宝石分类 要求&#xff1a;1.补充完成CNN的网络结构定义方法实现宝石识别 2.可尝试不同网络结构、参数等力求达到更好的效果 卷积神经网络 卷积神经网络是提取图像特征的经典网络&#xff0c;其结构一般包…

【hello C++】类和对象(下)

目录 1. 再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.3 explicit关键字 2. static成员 2.1 概念 2.2 特性 3. 友元 3.1 友元函数 3.2 友元类 4. 内部类 5.匿名对象 6.拷贝对象时的一些编译器优化 7. 再次理解类和对象 1. 再谈构造函数 1.1 构造函数体赋值 在创建对象…

Spring Boot项目使用 jasypt 加密组件进行加密(例如:数据库、服务的Key、等等进行加密)

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

【018】C++的指针数组和数组指针

C 指针数组和数组指针 引言一、指针数组1.1、数值的指针数组1.2、字符的指针数组1.3、二维字符数组 二、指针的指针三、数组指针3.1、数组首元素地址和数组首地址3.2、数组指针的使用示例3.3、二维数组和数组指针的关系 四、多维数组的物理存储总结 引言 &#x1f4a1; 作者简介…

从0实现基于Alpha zero的中国象棋AI(会分为多个博客,此处讲解蒙特卡洛树搜索)

从0实现基于Alpha zero的中国象棋AI 0.0、前言 ​ 题主对于阿尔法狗的实现原理好奇&#xff0c;加上毕业在即&#xff0c;因此选择中国象棋版的阿尔法zero&#xff0c;阿尔法zero是阿尔法狗的升级版。在完成代码编写的历程中&#xff0c;深刻感受到深度学习环境的恶劣&#x…

零门槛快速创业:GPT和AI工具的秘密武器

在不到一周的时间里&#xff0c;David创建了一个按需印刷的Etsy商店&#xff0c;该商店具有引人注目的标识和大量独特的文字和艺术。 我最近花了大约一周的时间来建立Etsy店面。在本文中&#xff0c;我将向你展示我如何&#xff08;可能更有趣的是&#xff0c;在哪里&#xff…

YOLOv5:TensorRT加速YOLOv5模型推理

YOLOv5&#xff1a;TensorRT加速YOLOv5模型推理 前言前提条件相关介绍TensorRT加速YOLOv5模型推理YOLOv5项目官方源地址将训练好的YOLOv5模型权重转换成TensorRT引擎YOLOv5 best.pt推理测试TensorRT Engine推理测试小结 参考 前言 由于本人水平有限&#xff0c;难免出现错漏&am…

笔试强训8

作者&#xff1a;爱塔居 专栏&#xff1a;笔试强训 作者简介&#xff1a;大三学生&#xff0c;希望和大家一起进步 day13 一. 单选 1.下列关于视图的说法错误的是&#xff1a; A 视图是从一个或多个基本表导出的表&#xff0c;它是虚表B 视图一经定义就可以和基本表一样被查询…

Python遍历网格中每个点

遍历网格中每个点 1. 问题描述2. Python实现2.1 网格参数初始化2.2 遍历赋值2.3 矩阵赋值1. 问题描述 最近需要实现一个对矩阵赋值并对矩阵表示的网格参数进行测试的任务,写了一段代码提供参考。 假设网格的长宽均为 2. Python实现 2.1 网格参数初始化 首先定义好需要划分…

【小呆的力学笔记】非线性有限元的初步认识【三】

文章目录 1.2.2 基于最小势能原理的线性有限元一般格式1.2.2.1 离散化1.2.2.2 位移插值1.2.2.3 单元应变1.2.2.4 单元应力1.2.2.5 单元刚度矩阵1.2.2.6 整体刚度矩阵1.2.2.7 处理约束1.2.2.8 求解节点载荷列阵1.2.2.9 求解位移列阵1.2.2.10 计算应力矩阵等 1.2.2 基于最小势能原…

基于深度学习的高精度推土机检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度推土机检测识别系统可用于日常生活中检测与定位推土机目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的推土机目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训…

通过location实现几秒后页面跳转

location对象属性 location对象属性 返回值location.href获取或者设置整个URLlocation.host返回主机&#xff08;域名&#xff09;www.baidu.comlocation.port 返回端口号&#xff0c;如果未写返回空字符串location.pathname返回路径location.search返回参数location.hash返回…

【SCADA】关于KingSCADA仿真驱动的应用

大家好&#xff0c;我是雷工&#xff01; 在有些时候我们需要用到虚拟仿真的数据&#xff0c;例如在效果演示时为了有良好的动态效果。在KingSCADA软件中可以通过Simulate驱动作为虚拟设备实现这一功能需求。 下面为大家演示该功能的应用&#xff1a; 一、KingIOServer工程设计…

Go实现跨域Cors中间件

概述 本版本主要实现cors中间件 github 地址&#xff1a;Sgin 欢迎star&#xff0c;将会逐步实现一个go web框架 内容 通过建造者模式创建我们的跨域中间件Cors \ 我们了解到&#xff0c;当使用XMLHttpRequest发送请求时&#xff0c;如果浏览器发现违反了同源策略就会自动加…

StableDiffusion入门教程

目录 介绍模型的后缀ckpt模型&#xff1a;safetensors模型文件夹VAE 模型在哪下载Hugging face:<https://huggingface.co/models>下载SD官方模型文生图模型标签介绍 C站&#xff1a;<https://civitai.com/>筛选模型的类型CheckPoint Type &#xff08;模型的类型&a…

Python学习笔记 - 探索元组Tuple的使用

欢迎各位&#xff0c;我是Mr数据杨&#xff0c;你们的Python导游。今天&#xff0c;我要为大家讲解一段特殊的旅程&#xff0c;它与《三国演义》有关&#xff0c;而我们的主角是元组&#xff08;tuple&#xff09;。 让我们想象这样一个场景&#xff0c;三国演义中的诸葛亮&am…

pandas数据预处理

pandas数据预处理 pandas及其数据结构pandas简介Series数据结构及其创建DataFrame数据结构及其创建 利用pandas导入导出数据导入外部数据导入数据文件 导出外部数据导出数据文件 数据概览及预处理数据概览分析利用DataFrame的常用属性利用DataFrame的常用方法 数据清洗缺失值处…

Cesium教程 (3) 矢量切片mvt-imagery-provider加载

Cesium教程 (3) 矢量切片mvt-imagery-provider加载 目录 0. 矢量切片 1. 开源项目 2. 环境 3. 代码 4. TODO 0. 矢量切片 WMTS&#xff1a;加载最快&#xff0c;图片格式&#xff0c;样式固定&#xff1b; WMS&#xff1a;加载数量大则慢&#xff0c;但可以点击查询等&am…

htmlCSS-----CSS选择器(上)

目录 前言&#xff1a; 1.初级选择器 &#xff08;1&#xff09;ID选择器 &#xff08;2&#xff09;class选择器 &#xff08;3&#xff09;标签选择器 &#xff08;4&#xff09;通配选择器 前言&#xff1a; CSS选择器是CSS页面处理的重要组成部分&#xff0c;前面讲到…