Bootstrap

qt实现简单的视频播放器

1、界面展示

效果图

2、功能简介

视频播放器的功能主要有打开文件添加视频、暂停/播放,上一个/下一页,改变音量、进度条等

3、实现思路

1、打开视频(QFielDialog)
一下选择多个视频,用QFileDialog::getOpenFileNames实现,将文件放到一个数据成员QStringlist中,使用QFileInfo info获取详细信息,filename()获取名字,再将之添加到listWidget中
2、视频列表(QlistWidget)
使用QFileInfo info获取详细信息,filename()获取名字,再将之添加到listWidget中。
3、暂停/继续(QMediaPlayer)
mediaPlayer play/[pause进行播放/暂停,记得修改图标
4、上一个/下一个(QFileInfo)
将下标修改,然后重新播放,需要重新设置媒体源
5、快退快进(QSlider)
修改进度条的value
6、截图
QScreen
9、播放顺序(QComboBox)
根据播放模式的不同。对下标进行对应的处理
10、进度条(QSlider)
时间/声音,可以滑动,修改value值
11、显示名字(QLineEdit)
滚动显示视频名字

做的时候是做了一个服务器端(Linux),一个客户端(QT),用到服务器的地方主要是登录注册以及查看历史观看的地方,只实现视频播放器的话不需要用到服务器端。

4、部分代码

#include "widget.h"
#include "ui_widget.h"
#include "clientwinmanager.h"
#include <QHostAddress>
static int socket_flag = 0;
QTcpSocket *Widget::tcpSocket = nullptr;
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("ZZH视频播放器");
    this->setWindowIcon(QIcon(":/image/太空兔.png"));
    //创建定时器对象
    this->timer = new QTimer(this);
    this->timer2 = new QTimer(this);
    this->timer2->start(1000);
    this->resize(1280,720);
    //实例化媒体播放器及视频播放
    this->mediaPlayer = new QMediaPlayer(this);
    this->videoWidget = new QVideoWidget(this);
    //实例化布局
    this->vbox = new QVBoxLayout(this);
    this->vbox1 = new QVBoxLayout(this);
    this->setLayout(this->vbox);//设置整个窗口为垂直布局
    this->hbox1 = new QHBoxLayout(this);
    this->hbox2 = new QHBoxLayout(this);
    this->hbox3 = new QHBoxLayout(this);
    this->hbox4 = new QHBoxLayout(this);
    this->hbox5 = new QHBoxLayout(this);
    //实例化按钮
    this->openBtn = new QPushButton("打开",this);
    this->preBtn = new QPushButton("上一个",this);
    this->rewindBtn = new QPushButton("快退",this);
    this->playBtn = new QPushButton("播放",this);
    this->playBtn->setIcon(this->style()->standardIcon(QStyle::SP_MediaPlay));
    this->forwardBtn = new QPushButton("快进",this);
    this->nextBtn = new QPushButton("下一个",this);
    this->shotBtn = new QPushButton("截图",this);
    this->loginBtn = new QPushButton("登录",this);
    this->loginBtn->setMaximumWidth(100);
    this->historyBtn = new QPushButton("历史",this);
    this->historyBtn->setMaximumWidth(100);
    //实例化标签
    this->timeLable = new QLabel("00:00:00/00:00:00",this);
    this->volumeLabel = new QLabel("50",this);
    this->volumeLabel->setMaximumWidth(200);
    this->videoNameLabel = new QLabel("未播放",this);
    this->userNameLabel = new QLabel("未登录",this);
    //this->playLabel = new QLabel("无视频",this);
    //实例化进度条
    this->timeSlider = new QSlider(this);
    this->volumeSlider = new QSlider(this);
    this->volumeSlider->setOrientation(Qt::Horizontal);
    this->timeSlider->setOrientation(Qt::Horizontal);
    this->volumeSlider->setMaximumWidth(200);
    this->volumeSlider->setRange(-1,101);
    this->volumeSlider->setValue(50);
    //实例化listWidget
    this->listWidget = new QListWidget(this);
    this->listWidget->setMaximumWidth(300);
    this->listWidget->setMinimumWidth(300);
   // this->playWidget = new QListWidget(this);
    //this->videoWidget->setGeometry(50,50,720,480);
    //this->playWidget->setGeometry(50,40,720,480);
   // this->videoWidget->setMinimumSize(this->playWidget->width(),this->playWidget->height());
    //实例化下拉框
    this->comboBox = new QComboBox(this);
    this->comboBox->addItem("顺序播放");
    this->comboBox->addItem("随机播放");
    this->comboBox->addItem("循环播放");
    //实例化lcd
    this->lcdNumber = new QLCDNumber(this);
    this->lcdNumber->setDigitCount(8);
    this->lcdNumber->setStyleSheet("background-color: green");//修改背景
    connect(this->timer2,SIGNAL(timeout()),this,SLOT(updateTime()));

    this->inde = 0;
    this->n = 0;
    this->dis_flag = 0;
    this->his_flag = 0;

    //进行布局
    this->hbox1->addWidget(this->videoNameLabel);
    this->hbox1->addWidget(this->lcdNumber);
    this->hbox1->addWidget(this->userNameLabel);
    this->hbox1->addWidget(this->historyBtn);
    this->hbox1->addWidget(this->loginBtn);
    //this->hbox1->addWidget(this->testBtn);


    this->hbox2->addStretch();
    this->hbox2->addLayout(this->vbox1);
    //this->hbox2->addWidget(this->playWidget);
    this->hbox2->addWidget(this->listWidget);

    this->hbox3->addWidget(this->timeLable);
    this->hbox3->addWidget(this->volumeLabel);

    this->hbox4->addWidget(this->timeSlider);
    this->hbox4->addWidget(this->volumeSlider);

    this->hbox5->addWidget(this->openBtn);
    this->hbox5->addWidget(this->preBtn);
    this->hbox5->addWidget(this->rewindBtn);
    this->hbox5->addWidget(this->playBtn);
    this->hbox5->addWidget(this->forwardBtn);
    this->hbox5->addWidget(this->nextBtn);
    this->hbox5->addWidget(this->shotBtn);
    this->hbox5->addWidget(this->comboBox);

    //垂直布局
    this->vbox->addLayout(this->hbox1);
    this->vbox->addLayout(this->hbox2);
    this->vbox->addLayout(this->hbox3);
    this->vbox->addLayout(this->hbox4);
    this->vbox->addLayout(this->hbox5);

    //关联
    connect(this->loginBtn,SIGNAL(clicked()),this,SLOT(do_loginBtn())); //登录
    connect(this->openBtn,SIGNAL(clicked()),this,SLOT(do_openBtn())); //打开文件
    connect(this->playBtn,SIGNAL(clicked()),this,SLOT(do_playBtn())); //播放/暂停
    connect(this->preBtn,SIGNAL(clicked()),this,SLOT(do_preBtn())); //上一首
    connect(this->nextBtn,SIGNAL(clicked()),this,SLOT(do_nextBtn())); //下一首
    connect(this->mediaPlayer,SIGNAL(positionChanged(qint64)),this,SLOT(updateTimeSlider(qint64))); //进度条变化
    connect(this->mediaPlayer,SIGNAL(durationChanged(qint64)),this,SLOT(setTimeSlider(qint64)));
    connect(this->timer,SIGNAL(timeout()),this,SLOT(updateTime_NameShow())); //滚动显示名字、显示歌曲已播放时间/总时间
    connect(this->rewindBtn,SIGNAL(clicked()),this,SLOT( do_rewindBtn())); //快退
    connect(this->forwardBtn,SIGNAL(clicked()),this,SLOT( do_forwardBtn()));//快进
    connect(this->listWidget,SIGNAL(itemDoubleClicked(QListWidgetItem*)),this,SLOT(doubleClickPlay(QListWidgetItem*)));//双击播放
    connect(this->volumeSlider,SIGNAL(sliderMoved(int)),this,SLOT(updateVolume(int))); //音量调节
    connect(this->historyBtn,SIGNAL(clicked()),this,SLOT(do_historyBtn())); //查看历史
    connect(this->shotBtn,SIGNAL(clicked()),this,SLOT(do_shotBtn())); //截图
    //connect(this->testBtn,SIGNAL(clicked()),this,SLOT(do_testBtn()));

    //通信


}

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

void Widget::setName(QString name)
{
    this->userNameLabel->setText(name);
    this->loginBtn->setText("登出");
}

void Widget::updateTime()
{
    //获取当前时间并转换成Qstring
    QString currentTime = QDateTime::currentDateTime().toString("hh:mm:ss");
    //更新lcd时间
    this->lcdNumber->display(currentTime);

}
//登录
#include <QMessageBox>
void Widget::do_loginBtn()
{
    if(this->loginBtn->text() == "登录")
    {
        //1、切换到登录界面
        this->tcpSocket = new QTcpSocket(this);//每次登录得时候实例化套接字
        connect(this->tcpSocket, SIGNAL(connected()), this, SLOT(connectedSlot()));
        clientWinManager *p = clientWinManager::getClientWin();
        this->close();
        p->loginWin->show();
        //2、连接服务器并提示
        if(socket_flag == 0)
        {
            this->tcpSocket->connectToHost(QHostAddress("192.168.206.212"), 9999);
            socket_flag = 1;
        }
    }
    else if (this->loginBtn->text() == "登出") {
        socket_flag = 0;
        this->loginBtn->setText("登录");
        this->userNameLabel->setText("未登录");
        //断开,拼接字符串,发给服务器
        char str[100] = {'\0'};
        sprintf(str,"dis");
        Widget::tcpSocket->write(str);
        this->tcpSocket->disconnectFromHost();
        this->tcpSocket = nullptr;//bug,断开之后不能重新连接
        QMessageBox::information(this,"tips","退出,断开服务器");
    }
}
//打开视频文件
#include <QFileDialog>
void Widget::do_openBtn()
{
    this->nameList.clear();
    this->listWidget->clear();//清空表单
    this->nameList = QFileDialog::getOpenFileNames(this,"select",".","MKV(*.mkv)");
    if(nameList.size() == 0)
    {
          return;
    }
    for(int i = 0;i < nameList.size();i++)  //循环的将选中的文件加入到listWidget
    {
        QFileInfo info(nameList.at(i));
        QListWidgetItem *item = new QListWidgetItem(info.fileName(),this->listWidget);
        this->listWidget->addItem(item);
        item->setToolTip(nameList.at(i));//----------
    }

    QString fileName = nameList.at(0);//默认播放打开的第一个视频
    this->mediaPlayer->setMedia(QUrl(fileName));//设置媒体源
    QFileInfo info(fileName);//获取文件全部信息
    this->videoName = info.fileName() + "      ";
    this->videoNameLabel->setText(this->videoName);
    this->mediaPlayer->setVolume(50);//设置音量
    this->vbox1->addWidget(this->videoWidget);
    this->mediaPlayer->setVideoOutput(this->videoWidget);
    //this->mediaPlayer->setVideoOutput(this->videoWidget);
    this->mediaPlayer->play();
    this->timer->start(1000);
    this->playBtn->setIcon(this->style()->standardIcon(QStyle::SP_MediaPause));
    if(this->userNameLabel->text() != "未登录")
    {
        //有用户登录,将该用户看过的视频存放到数据库
        //先转换类型
        char str[100] = {'\0'};
        QByteArray userName = this->userNameLabel->text().toLatin1();//用户名
        QByteArray vidName = this->videoName.toLatin1(); //视频名字
        sprintf(str,"His#%s#%s",userName.data(),vidName.data()); //拼接字符串
        qDebug() << videoName.data();
        Widget::tcpSocket->write(str);
    }
}
//播放/暂停
void Widget::do_playBtn()
{
    int state = this->mediaPlayer->state();
    if(state == QMediaPlayer::PlayingState)
    {
        //正在播放,暂停播放,图标修改成播放
        this->mediaPlayer->pause();
        this->playBtn->setText("播放");
        this->playBtn->setIcon(this->style()->standardIcon(QStyle::SP_MediaPlay));

    }
    else if (state == QMediaPlayer::PausedState) {
        //暂停,继续播放,图标修改为暂停
        this->mediaPlayer->play();
        this->playBtn->setText("暂停");
        this->playBtn->setIcon(this->style()->standardIcon(QStyle::SP_MediaPause));
    }
}
//上一个
void Widget::do_preBtn()
{
    this->inde--;
    if(this->inde < 0)
    {
        this->inde = this->nameList.size() - 1;
    }
    this->mediaPlayer->stop();
    QFileInfo fileName(this->nameList.at(this->inde));//获取文件信息
    this->mediaPlayer->setMedia(QUrl(this->nameList.at(this->inde)));//设置媒体源
    this->videoNameLabel->setText(fileName.fileName());//修改标题
    this->mediaPlayer->setVideoOutput(this->videoWidget);
    this->videoName = fileName.fileName();
    this->mediaPlayer->play();
    this->timer->start(1000);
    if(this->userNameLabel->text() != "未登录")
    {
        //有用户登录,将该用户看过的视频存放到数据库
        //先转换类型
        char str[100] = {'\0'};
        QByteArray userName = this->userNameLabel->text().toLatin1();//用户名
        QByteArray vidName = fileName.fileName().toLatin1(); //视频名字
        sprintf(str,"His#%s#%s",userName.data(),vidName.data()); //拼接字符串
        Widget::tcpSocket->write(str);
    }
}
//下一个
void Widget::do_nextBtn()
{
    this->inde++;
    if(this->inde > this->nameList.size() - 1)
    {
        this->inde = 0;
    }
    this->mediaPlayer->stop();
    QFileInfo fileName(this->nameList.at(this->inde));//获取文件信息
    this->mediaPlayer->setMedia(QUrl(this->nameList.at(this->inde)));//设置媒体源
    this->videoNameLabel->setText(fileName.fileName());//修改标题
    this->mediaPlayer->setVideoOutput(this->videoWidget);
    this->videoName = fileName.fileName();
    this->mediaPlayer->play();
    this->timer->start(1000);
    if(this->userNameLabel->text() != "未登录")
    {
        //有用户登录,将该用户看过的视频存放到数据库
        //先转换类型
        char str[100] = {'\0'};
        QByteArray userName = this->userNameLabel->text().toLatin1();//用户名
        QByteArray vidName = fileName.fileName().toLatin1(); //视频名字
        sprintf(str,"His#%s#%s",userName.data(),vidName.data()); //拼接字符串
        Widget::tcpSocket->write(str);
    }
}

//给进度条设置范围
void Widget::setTimeSlider(qint64 duration)
{
    this->timeSlider->setRange(0,int(duration));
}
//根据视频播放的位置修改进度条
void Widget::updateTimeSlider(qint64 position)
{
    this->timeSlider->setValue(int(position));
}

//滚动显示名字、修改文本时间
//实现播放模式
#include <QFileInfo>
void Widget::updateTime_NameShow()
{
    /*
    根据n的值显示内容
    */
    this->n++;
    if(this->n == this->videoName.size())
    {
        this->n = 0;
    }
    this->videoNameLabel->setText(this->videoName.mid(this->n));//滚动显示
    //获取总时间跟当前播放时长
    qint64 dur = this->mediaPlayer->duration();
    qint64 pos = this->mediaPlayer->position();
    //实例化两个对象,用来显示
    QTime durTime(0,0,0);
    QTime posTime(0,0,0);
    this->timeLable->setText(posTime.addMSecs(int(pos)).toString("mm:ss") + "/" + durTime.addMSecs(int(dur)).toString("mm:ss"));

    //根据播放模式进行播放
    /*
     * 1、顺序播放,下标++,最后一首的时候,下标置为0(dur == pos的时候结束)
     * 2、随机播放,qrand()给下标一个随机值
     * 3、循环播放,下表不变
    */
    if(dur == pos)
    {
        if(this->comboBox->currentText() == "顺序播放")
        {
            this->inde++;
            if(this->inde > this->nameList.size() - 1)
            {
                this->inde = 0;
            }
        }
        else if (this->comboBox->currentText() == "随机播放") {
            this->inde = qrand() % this->nameList.size();
        }
        else if (this->comboBox->currentText() == "循环播放"){
            this->inde = this->inde+0;
        }
        // 开始播放()
        QFileInfo fileName(this->nameList.at(this->inde));//获取文件信息
        this->mediaPlayer->setMedia(QUrl(this->nameList.at(this->inde)));//设置媒体源
        this->videoNameLabel->setText(fileName.fileName());//修改标题
        this->mediaPlayer->setVideoOutput(this->videoWidget);
        this->mediaPlayer->play();
        this->timer->start(1000);
    }
}
//快退,播放时间减少5s
#include <QMessageBox>
void Widget::do_rewindBtn()
{
    //判断当前播放时间是否小于5s
    //判断完之后要修改文本、滑动块,
    //获取总时间跟当前播放时长
    qint64 dur = this->mediaPlayer->duration();
    qint64 pos = this->mediaPlayer->position();
    //实例化两个对象,用来显示
    qDebug() << int(pos);
    QTime durTime(0,0,0);
    QTime posTime(0,0,0);
    if(int(pos) <= 5000)
    {
        this->timeSlider->setValue(0);
        this->mediaPlayer->setPosition(0);
        this->timeLable->setText(posTime.addMSecs(0).toString("mm:ss") + "/" + durTime.addMSecs(int(dur)).toString("mm:ss"));
    }
    else {
        this->timeSlider->setValue(int(pos) - 5000);
        this->mediaPlayer->setPosition(int(pos) - 5000);
        this->timeLable->setText(posTime.addMSecs(int(pos)-5000).toString("mm:ss") + "/" + durTime.addMSecs(int(dur)).toString("mm:ss"));
    }
}
//快进
void Widget::do_forwardBtn()
{
    //判断剩余播放时间是否小于5s
    //获取总时间跟当前播放时长
    qint64 dur = this->mediaPlayer->duration();
    qint64 pos = this->mediaPlayer->position();
    //实例化两个对象,用来显示
    QTime durTime(0,0,0);
    QTime posTime(0,0,0);
    if(int(dur)-int(pos) <=5000)
    {
        this->timeSlider->setValue(int(dur));
        this->mediaPlayer->setPosition(int(dur));
        this->timeLable->setText(posTime.addMSecs(int(dur)).toString("mm:ss") + "/" + durTime.addMSecs(int(dur)).toString("mm:ss"));
    }
    else {
        this->timeSlider->setValue(int(pos) + 5000);
        this->mediaPlayer->setPosition(int(pos) + 5000);
        this->timeLable->setText(posTime.addMSecs(int(pos)+5000).toString("mm:ss") + "/" + durTime.addMSecs(int(dur)).toString("mm:ss"));
    }
}
void Widget::doubleClickPlay(QListWidgetItem *item)//参数为双击的目标信息
{
    /*
     * 1、获取listWidget中下标位置
    2、设置媒体源、播放选中的歌曲
    3、修改名字
    4、修改图标
    5、定时器启动
    */
    this->inde = this->listWidget->currentRow(); //获取当前下标
    this->mediaPlayer->setMedia(QUrl(item->toolTip()));
    this->videoNameLabel->setText(item->text());
    this->videoName = item->text();
    qDebug() << videoName;
    this->mediaPlayer->play();
    this->timer->start(1000);
    this->playBtn->setIcon(this->style()->standardIcon(QStyle::SP_MediaPause));
    if(this->userNameLabel->text() != "未登录")
    {
        //有用户登录,将该用户看过的视频存放到数据库
        //先转换类型
        char str[100] = {'\0'};
        QByteArray userName = this->userNameLabel->text().toLatin1();//用户名
        QByteArray vidName = item->text().toLatin1(); //视频名字
        sprintf(str,"His#%s#%s",userName.data(),vidName.data()); //拼接字符串
        qDebug() << userName.data();
        Widget::tcpSocket->write(str);
    }
}

//修改音量
#include <string.h>
void Widget::updateVolume(int positoin)
{
    this->mediaPlayer->setVolume(positoin); //修改媒体音量
   // strcat("音量:",this->volumeSlider->value());
    int i = this->volumeSlider->value();
    this->volumeLabel->setText(QString::number(i)); //将int转换成对应的类型,修改文本
}

void Widget::do_historyBtn()
{
    //用户只有才能查看观看历史,没登录提示用户登录
    if(this->userNameLabel->text() == "未登录")
    {
        QMessageBox::warning(this,"tips","请先登录");
    }
    else {
        //获取历史记录,存放到listWidget中
        //先获取有几条记录,再循环的获取具体信息,先清空,通过addItem加
        //先给服务器端发送要接收历史记录的消息
        if(this->his_flag == 0)
        {
            this->his_flag = 1;
            char str[100] = {'\0'};
            QByteArray userName = this->userNameLabel->text().toLatin1();//用户名
            sprintf(str,"Get#%s",userName.data());
            connect(Widget::tcpSocket,SIGNAL(readyRead()),this,SLOT(readData()));
            Widget::tcpSocket->write(str);
        }
    }
}
//截图
#include <QScreen>
void Widget::do_shotBtn()
{
     qDebug()<<"shot";
    QScreen *screen = QGuiApplication::primaryScreen();
    //拼接图片的名字
    QString filePathName = "cut-";

    filePathName += QDateTime::currentDateTime().toString("yyyy-MM-dd hh-mm-ss-zzz");

    filePathName += ".png";


    QPixmap pixmap = screen->grabWindow(0);

    if(!pixmap.save(filePathName,"png"))

    {

        qDebug()<<"cut save png failed"<<endl;

    }


    QRect geo = this->geometry();

    QRect appGeo = geo; // 整个应用程序在图片中的位置。

    geo = this->videoWidget->geometry(); // 播放视频在图片中的位置。

    QRect copyGeo;

    copyGeo.setX(geo.x() + appGeo.x() ); // x=三个x相加

    copyGeo.setY(geo.y() + appGeo.y() );

    copyGeo.setWidth(geo.width());

    copyGeo.setHeight(geo.height());

    QPixmap pixmapCopy = pixmap.copy(copyGeo); // copy图片

    filePathName.prepend("Copy+");

    if(pixmapCopy.save(filePathName,"png"))

    {

        QMessageBox::information(this,"tips","截取成功");

    }
}
//接收消息
void Widget::readData()
{
    //接收历史观看,一行一行显示,以#分割
    if(this->his_flag == 1)
    {
        QByteArray recv = Widget::tcpSocket->read(128); //读取数据
        QString str = QString(recv);//格式转换,重新走下构造
        qDebug()<< recv;
        //先获取数据的数量
        QStringList list = str.split('#');
        int size = str.split("#").at(0).toInt();
        this->listWidget->clear();//清空之前显示的内容
        //以#分割开
        for(int i = 1;i <= size;i++)
        {
            QString chr = list[i];
            this->listWidget->addItem(chr);
        }
        this->his_flag = 0;
    }
}

//连接服务器端
void Widget::connectedSlot(){
    QMessageBox::information(this,"tips","连接服务器成功");
}



;