一个简单播放器(QMediaPlayer, 代码布局)

1.先上结果 和 代码

  

头文件:

#ifndef VIDEOPLAYER_H
#define VIDEOPLAYER_H

#include <QWidget>
#include <QObject>
#include <QVideoWidget>
#include <QMediaPlayer>
#include <QAudioOutput>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
class videoPlayer : public QWidget
{
    Q_OBJECT
public:
    videoPlayer(QString bg, QWidget* parent = nullptr);

    QString formatTime(qint64 time);
    void getListFromDB(void);

private slots:


private:
    QMediaPlayer* player;
    QVideoWidget* videoWidget;
    QAudioOutput* audioOutput;
    QStringList* filepathList;
    int curListIndex = 0;
    QSqlDatabase database;// 用于建立和数据库的连接



signals:
};

#endif // VIDEOPLAYER_H

源文件 

#include "videoplayer.h"
#include <QGridLayout>
#include <QPalette>
#include <QLabel>
#include <QPixmap>
#include <QPushButton>
#include <QSlider>
#include <QSpacerItem>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QDir>
#include <QFileDialog>
#include <QMessageBox>
#include <QAudioFormat>
#include <QTimer>

videoPlayer:: videoPlayer(QString bg, QWidget* parent)
{
    this->setParent(parent);
    filepathList = new QStringList();
    /***********************************************************************main widget***********************************************************************/
    QWidget* widget =  new QWidget(this);
    QGridLayout* grid = new QGridLayout(widget);
    widget->setFixedSize(400, 300);
    this->move((parent->width()-widget->width())/2, (parent->height()-widget->height())/2);
    widget->setStyleSheet(QString(".QWidget{background-color:rgba(200,100,186,10);}").append(".QWidget{border-image:url(")
                            .append(bg).append(");background-repeat:no-repeat;background-position:center;}")
                            .append(".QWidget{border:1px solid black;}")
                            .append(".QWidget{border-radius:10px;}")
                            .append("QSlider::groove:horizontal {border: 0px solid #bbb;}")
                              .append("QSlider::sub-page:horizontal{background:rgb(180,60,140);border-radius:4px;margin-top:7px;margin-bottom:7px;}")
                              .append("QSlider::add-page:horizontal{background:rgb(238,152,10);border:0px solid #777;border-radius:3px;margin-top:9px;margin-bottom:9px;}")
                              .append("QSlider::handle:horizontal{background:rgb(163,77,89);width: 10px;border:1px solid rgb(193,204,208);border-radius:4px;margin-top:4px;margin-bottom:4px;}")
                              .append("QSlider::handle:horizontal:hover{background:rgb(163,77,89);width: 10px;border:1px solid rgb(193,204,208);border-radius:5px; margin-top:4px;margin-bottom:4px;}")
                            /*.append(".QSlider{border:1px solid black;{border-radius:10px;}")*/
                          );
    widget->move(0,0);

    QFont font("华文新魏",10);
    QPixmap pix;
    QVBoxLayout* vedoLayout = new QVBoxLayout;
    videoWidget = new QVideoWidget(widget);
    // QLabel* vedo = new QLabel("lalala",widget);
    // vedo->resize(200,200);
    // vedo->setPixmap(QPixmap(":/pic/lotso (12).jpg"));
    vedoLayout->addWidget(videoWidget);
    QLabel* totalTimeLabel = new QLabel("00:00:00",widget);totalTimeLabel->setFont(font);
    QLabel* voiceTitleLabel = new QLabel("音量",widget);voiceTitleLabel->setFont(font);voiceTitleLabel->setFixedSize(30,30);voiceTitleLabel->setAlignment(Qt::AlignJustify|Qt::AlignVCenter);
    voiceTitleLabel->setPixmap(QPixmap(":/vedioRes/volumn.png").scaled(30,30));
    QLabel* voiceLabel = new QLabel("100",widget);voiceLabel->setFont(font);voiceLabel->setFixedWidth(30);voiceLabel->setAlignment(Qt::AlignJustify|Qt::AlignVCenter);
    QPushButton* startBtn = new QPushButton(widget);startBtn->setFixedSize(40,30);startBtn->setStyleSheet("QPushButton{border:0px;border-image:url(:/vedioRes/start.png)}");
    QPushButton* stopBtn = new QPushButton(widget);stopBtn->setFixedSize(40,30);stopBtn->setStyleSheet("QPushButton{border:0px;border-image:url(:/vedioRes/pause_no.png)}");
    QPushButton* nextBtn = new QPushButton(widget);nextBtn->setFixedSize(40,30);nextBtn->setCheckable(true);nextBtn->setChecked(false);nextBtn->setStyleSheet("QPushButton{border:0px;border-image:url(:/vedioRes/next.png)}QPushButton:pressed{border:0px;border-image:url(:/vedioRes/next_no.png)}");
    QPushButton* replayBtn = new QPushButton(widget);replayBtn->setFixedSize(40,30);replayBtn->setCheckable(true);replayBtn->setChecked(false);replayBtn->setStyleSheet("QPushButton{border:0px;border-image:url(:/vedioRes/replay_no.png)}QPushButton:checked{border-image:url(:/vedioRes/replay.png)}");
    qDebug()<<QString("the button is %1").arg(nextBtn->isChecked());
    QSlider* processSlider = new QSlider(Qt::Horizontal,widget);
    QSlider* voiceSlider = new QSlider(Qt::Horizontal,widget);voiceSlider->setFixedWidth(70);voiceSlider->setMaximum(100);voiceSlider->setRange(0,100);voiceSlider->setValue(100);
    QSpacerItem* spacer = new QSpacerItem(100,30);
    grid->addLayout(vedoLayout,     0,0,1,7);//grid->addWidget(vedo,           0,0,1,7);
    grid->addWidget(processSlider,  1,0,1,6);
    grid->addWidget(totalTimeLabel, 1,6);
    grid->addWidget(startBtn,       2,0);
    grid->addWidget(stopBtn,        2,1);
    grid->addWidget(nextBtn,        2,2);
    grid->addWidget(replayBtn,      2,3);
    //grid->addItem(spacer,           2,3);
    grid->addWidget(voiceTitleLabel,2,4);
    grid->addWidget(voiceSlider,    2,5);
    QHBoxLayout* layout = new QHBoxLayout;
    QSpacerItem* spacerTemp = new QSpacerItem(6,30);
    layout->addSpacerItem(spacerTemp);
    layout->addWidget(voiceLabel);
    QLabel* labtemp = new QLabel(widget);labtemp->setPixmap(QPixmap(":/pic/lotso (20).jpg").scaled(30,30));
    layout->addWidget(labtemp);
    grid->addLayout(layout,         2,6);//grid->addWidget(voiceLabel,2,6);d

    //voiceSlider->setStyleSheet("QSlider{border:0px solid #bbb;border-radius:0px;}");
    voiceSlider->setStyleSheet(QString("QSlider::groove:horizontal {border: 0px solid #bbb;}")
                            .append("QSlider::sub-page:horizontal{background:rgb(180,60,140);border-radius:4px;margin-top:7px;margin-bottom:7px;}")
                            .append("QSlider::add-page:horizontal{background:rgb(238,152,10);border:0px solid #777;border-radius:3px;margin-top:9px;margin-bottom:9px;}")
                            .append("QSlider::handle:horizontal{background:rgb(163,77,89);width: 10px;border:1px solid rgb(193,204,208);border-radius:4px;margin-top:4px;margin-bottom:4px;}")
                            .append("QSlider::handle:horizontal:hover{background:rgb(163,77,89);width: 10px;border:1px solid rgb(193,204,208);border-radius:5px; margin-top:4px;margin-bottom:4px;}")
                               );


    /***********************************************************************logic***********************************************************************/
    player = new QMediaPlayer(this);
    audioOutput = new QAudioOutput(this);
    player->setVideoOutput(videoWidget);
    player->setAudioOutput(audioOutput);//player->audioOutput()->setVolume(1);
    void (QSlider:: *sliderValueChangedSignal)(int) = &QSlider::valueChanged;
    void (QLabel:: *labelSetNumSlot)(int) = &QLabel::setNum;
    connect(player,&QMediaPlayer::positionChanged,[=](qint64 position){
        if(player->duration() > 0)
        {
            int progress = static_cast<int>(position);
            processSlider->setValue(progress);
            totalTimeLabel->setText(formatTime(position));
            //重播
            if(position == player->duration())
            {
                player->stop();
                if(replayBtn->isChecked() == true)
                {
                    QTimer::singleShot(500,[=](){
                        player->play();
                    });
                }
                else
                {
                    QTimer::singleShot(1000,[=](){
                        curListIndex++;
                        if(curListIndex<filepathList->count())
                        {
                            player->setSource(QUrl::fromLocalFile(filepathList->at(curListIndex)));
                        }
                        else
                        {
                            curListIndex = 0;
                            player->setSource(QUrl::fromLocalFile(filepathList->at(curListIndex)));
                        }
                        player->play();
                    });
                }
            }
        }
    });

    connect(processSlider, &QAbstractSlider::sliderMoved, [=](int pos){
        qint64 progress = static_cast<qint64>(pos);
        if(player->duration() > 0)
        {
            player->setPosition(progress);
        }
    });
    connect(player, &QMediaPlayer::durationChanged,[=](){
        qDebug()<<"!!!!!!!!!!!!!!!!!!!!!!!!!";
        qint64 totaltime = player->duration();
        totalTimeLabel->setText(formatTime(totaltime));
        //视频进度条初始化,duration为视频总长,单位毫秒
        processSlider->setRange(0, totaltime);

    });
    // connect(audioOutput, &QAudioOutput::volumeChanged, [=](){
    //     voiceSlider->setValue(audioOutput->volume());
    // });
    connect(voiceSlider, sliderValueChangedSignal, voiceLabel, labelSetNumSlot);
    connect(voiceSlider, sliderValueChangedSignal, audioOutput,  [=](int vol){
        audioOutput->setVolume(((float)vol)/100);
        if(vol == 0){voiceTitleLabel->setPixmap(QPixmap(":/vedioRes/volumn_no.png").scaled(30,30));}
        else{voiceTitleLabel->setPixmap(QPixmap(":/vedioRes/volumn.png").scaled(30,30));}
    });
    connect(startBtn,&QPushButton::clicked,[=](){
        player->play();
        startBtn->setStyleSheet("QPushButton{border:0px;border-image:url(:/vedioRes/start_no.png)}");
        startBtn->setDisabled(true);
        stopBtn->setStyleSheet("QPushButton{border:0px;border-image:url(:/vedioRes/pause.png)}");
        stopBtn->setEnabled(true);
    });
    connect(stopBtn,&QPushButton::clicked,[=](){
        player->pause();
        stopBtn->setStyleSheet("QPushButton{border:0px;border-image:url(:/vedioRes/pause_no.png)}");
        stopBtn->setDisabled(true);
        startBtn->setStyleSheet("QPushButton{border:0px;border-image:url(:/vedioRes/start.png)}");
        startBtn->setEnabled(true);
    });
    connect(nextBtn,&QPushButton::clicked,[=](){
        player->stop();
        //qDebug()<<QString("the button is %1").arg(nextBtn->isChecked());
        QTimer::singleShot(500,[=](){
            curListIndex++;
            if(curListIndex<filepathList->count())
            {
                player->setSource(QUrl::fromLocalFile(filepathList->at(curListIndex)));
            }
            else
            {
                curListIndex = 0;
                player->setSource(QUrl::fromLocalFile(filepathList->at(curListIndex)));
            }
            player->play();
        });
        startBtn->setStyleSheet("QPushButton{border:0px;border-image:url(:/vedioRes/start_no.png)}");
        startBtn->setDisabled(true);
        stopBtn->setStyleSheet("QPushButton{border:0px;border-image:url(:/vedioRes/pause.png)}");
        stopBtn->setEnabled(true);
    });
    connect(replayBtn,&QPushButton::clicked,[=](){
        qDebug()<<QString("the button is %1").arg(replayBtn->isChecked());
    });
    /***********************************************************************play***********************************************************************/
    // QString currentpath = QDir::homePath();//获取系统当前目录
    // QString openfiletitle = "请选择文件";//title
    // QString filefilter = "all(*.*);;MP4(*.mp4);;OGG(*.ogg);;MP3(*.mp3)";//"all(*.*);;MP4(*.mp4);;image(*.jpg);;file(*.txt)";//选择文件
    // //QStringList* filepath = new QStringList(QFileDialog::getOpenFileNames(this,openfiletitle,currentpath,filefilter));//(this, openfiletitle, currentpath, filefilter);
    // filepathList = new QStringList(QFileDialog::getOpenFileNames(this,openfiletitle,currentpath,filefilter));

    // // if(filepath.isEmpty())
    // // {
    // //     QMessageBox::warning(this, "打开文件", "文件不能为空!!!!!");
    // //     return;
    // // }
    // for(const QString &fileName : *filepathList) {
    //     qDebug() << "Selected file:" << fileName;
    // }
    // //QFileInfo info(filepath);//获取文件信息
    // player->setSource(QUrl::fromLocalFile(filepathList->at(0)));//setMedia(QUrl::fromLocalFile(filepath));
    // //player->play();//播放
}

QString videoPlayer::formatTime(qint64 time)
{
    int seconds = (time / 1000) % 60;
    int minutes = (time / 60000) % 60;
    int hours = (time / 3600000) % 24;
    return QString("%1:%2:%3")
        .arg(hours, 2, 10, QLatin1Char('0'))
        .arg(minutes, 2, 10, QLatin1Char('0'))
        .arg(seconds, 2, 10, QLatin1Char('0'));
}
void videoPlayer::getListFromDB(void)
{
    QSqlQuery sqlQuery;

    if (QSqlDatabase::contains("qt_sql_default_connection"))
    {
        database = QSqlDatabase::database("qt_sql_default_connection");
    }
    else
    {
        // 建立和SQlite数据库的连接
        database = QSqlDatabase::addDatabase("QSQLITE");
        // 设置数据库文件的名字
        database.setDatabaseName("MyDataBase.db");
    }
    if (!database.open())
    {
        qDebug() << "Error: Failed to connect database." << database.lastError();return;
    }

    if(!database.tables().contains(QString("videoList")))
    {
        qDebug() << "Error: Failed to connect database." << database.lastError();

        // 构建创建数据库的sql语句字符串
        QString createSql = QString("CREATE TABLE ").append("videoList").append(" (\
                                                                              id INT PRIMARY KEY NOT NULL,\
                                                                              path TEXT NOT NULL,\
                                                                              type TEXT NOT NULL)");
        sqlQuery.prepare(createSql);
        // 执行sql语句
        if(!sqlQuery.exec())
        {
            qDebug() << "Error: Fail to create table. " << sqlQuery.lastError();return;
        }
        /***********************************************************************play***********************************************************************/
        QString currentpath = QDir::homePath();//获取系统当前目录
        QString openfiletitle = "请选择文件";//title
        QString filefilter = "all(*.*);;MP4(*.mp4);;OGG(*.ogg);;MP3(*.mp3)";//"all(*.*);;MP4(*.mp4);;image(*.jpg);;file(*.txt)";//选择文件
        //QStringList* filepath = new QStringList(QFileDialog::getOpenFileNames(this,openfiletitle,currentpath,filefilter));//(this, openfiletitle, currentpath, filefilter);
        filepathList = new QStringList(QFileDialog::getOpenFileNames(this,openfiletitle,currentpath,filefilter));
        int indexID = 0;
        for(const QString &fileName : *filepathList) {
            indexID++;
            qDebug() << "Selected file:" << fileName;
            sqlQuery.prepare(QString("INSERT INTO ").append("videoList").append(" VALUES(:id,:path,:type)"));
            sqlQuery.bindValue(":id", indexID);
            sqlQuery.bindValue(":path", fileName);
            sqlQuery.bindValue(":type", QFileInfo(fileName).suffix());
            if(!sqlQuery.exec())
            {
                qDebug() << "Error: Fail to insert data. " << sqlQuery.lastError();
            }
            else
            {
                // do something
            }
        }
        //QFileInfo info(filepath);//获取文件信息
        player->setSource(QUrl::fromLocalFile(filepathList->at(0)));//setMedia(QUrl::fromLocalFile(filepath));
        //player->play();//播放
    }
    else
    {
        sqlQuery.exec(QString("SELECT path FROM ").append("videoList").append(" WHERE type IN ('mp3', 'MP3', 'ogg', 'OGG', 'mp4', 'MP4')"));//.append(name).append("'"));
        if(!sqlQuery.exec())
        {
            qDebug() << "Error: Fail to query table. " << sqlQuery.lastError();
        }
        else
        {
            filepathList->clear();
            while(sqlQuery.next())
            {
                filepathList->append(sqlQuery.value(0).toString());
                // data->id = sqlQuery.value(0).toInt();
                // data->name = sqlQuery.value(1).toString();
                // data->age = sqlQuery.value(2).toInt();
                // data->password = sqlQuery.value(3).toString();
                qDebug()<<sqlQuery.value(0).toString();
            }
            player->setSource(QUrl::fromLocalFile(filepathList->at(0)));//setMedia(QUrl::fromLocalFile(filepath));
        }
    }






}

 2.其中问题点

1)QT6的QMediaPlayer:

         首先实现播放器工程需要三个类对象:

                1.QMediaPlayer 自然是需要的;

                2.QVideoWidget用于承载(不知道用词是否合适哈)播放图像资源;

                3.QAudioOutput新版Qt的音频需要使用其来管理。

        然后就是将为player添加视屏资源 和 音频资源管理的对象:

2)代码布局方式

结果中展现的布局其实是一个三行七列的栅格式布局:

如何统一设置布局中两个QSlider 的样式:其中所有页面下的子控件的父类都是整个播放器的widget,所以在以下代码设置了QSlider的样式,将进度条 和 音量条的样式统一设置;

widget->setStyleSheet(QString(".QWidget{background-color:rgba(200,100,186,10);}").append(".QWidget{border-image:url(")
                            .append(bg).append(");background-repeat:no-repeat;background-position:center;}")
                            .append(".QWidget{border:1px solid black;}")
                            .append(".QWidget{border-radius:10px;}")
                            .append("QSlider::groove:horizontal {border: 0px solid #bbb;}")
                              .append("QSlider::sub-page:horizontal{background:rgb(180,60,140);border-radius:4px;margin-top:7px;margin-bottom:7px;}")
                              .append("QSlider::add-page:horizontal{background:rgb(238,152,10);border:0px solid #777;border-radius:3px;margin-top:9px;margin-bottom:9px;}")
                              .append("QSlider::handle:horizontal{background:rgb(163,77,89);width: 10px;border:1px solid rgb(193,204,208);border-radius:4px;margin-top:4px;margin-bottom:4px;}")
                              .append("QSlider::handle:horizontal:hover{background:rgb(163,77,89);width: 10px;border:1px solid rgb(193,204,208);border-radius:5px; margin-top:4px;margin-bottom:4px;}")
                            /*.append(".QSlider{border:1px solid black;{border-radius:10px;}")*/
                          );

网络媒体播放器含详细的文档 <!-- // // 播放程序的基本设定 // // ?自动播放? // 设定当播放器加载页面时,是否自动播放(Auto Start)媒体档案: // true = 自动播放 (一般站长会选择这个方式) // false = 不要自动播放,等待使用者启动播放器 var blnAutoStart = true; // ?随机播放? // 设定曲目的预设播放顺序,是否随机(随机数/Random Playing)播放媒体档案: // true = 随机播放 (一般站长会选择这个方式) // false = 根据我所排列的顺序,循序播放 var blnRndPlay = false; // ?显示媒体标题方块? // 设定播放面板上是否要显示媒体标题: // true = 显示媒体标题 // false = 不要显示媒体标题,将方块隐藏起来 var blnShowTitle = true; // ?显示时间长度方块? // 设定播放面板上是否要显示时间长度: // true = 显示时间长度 // false = 不要显示时间长度,将方块隐藏起来 var blnShowTime = true; // ?在状态列显示文字讯息? // 设定是否要在浏览器的状态列(Status Bar),显示播放器的目前动作: // true = 在状态列显示播放器文字讯息 (适合在隐藏媒体标题/时间长度方块的情况下使用) // false = 不要在状态列显示播放器文字讯息 // (如果您在设定播放清单项目时,使用了像 〹 的『&句柄』,必须将此项设为 false) var blnStatusBar = true; // ?显示音量控制按钮? // 设定播放面板上是否要显示音量控制(Volume Control-包括静音模式)的按钮: // true = 显示音量控制,容许使用者调校音量 // false = 不显示音量控制,将按钮隐藏起来 var blnShowVolCtrl = true; // ?显示播放清单按钮? // 设定播放面板上是否要显示播放清单(Playlist)按钮: // true = 显示播放清单按钮,让使用者检视播放清单内容及挑选曲目 // false = 不显示播放清单按钮,使用者无法检视播放清单内容及挑选曲目 var blnShowPlist = true; // ?使用字幕功能,开启字幕框? // 设定是否使用SMIL字幕功能(Closed Captioning-须配合扩展名为"SMI"的纯文本文件使用): // true = 使用字幕功能,在字幕框中显示同步歌词或文字讯息(也可以包含图片等信息) // false = 关闭字幕功能 var blnUseSmi = false; // ?循环播放? // 设定当所有曲目播放完毕后,是否重新播放所有曲目(循环播放/Loop Tracks): // true = 使用循环播放功能 (一般站长会选择这个方式) // false = 不使用循环播放功能,当所有曲目播放完毕后停止播放 var blnLoopTrk = true; // ?弹出窗口显示媒体档案信息? // 设定在开始播放每一首曲目时,是否弹出窗口显示媒体档案信息(Media Info): // true = 显示媒体档案信息 (请认真考虑清楚,因为浏览者可能会感到厌烦的,此功能只适合测试用) // false = 不显示媒体档案信息 var blnShowMmInfo = false; // ?播放面板上,动态按钮的颜色设定值 // 以下两个设定值是用来指定播放面板上,动态按钮 (例如: 重复曲目,暂停-继续,静音...) // 在不同状态下 (On/Off) 所显示的背景颜色。请注意,其中 btnOffColor 的颜色,必须与 // 在播放面板样式表 (exobud.css) 中所设定,.buttons 样式 background-color 的一样。 // 您可以使用16位颜色码(#FFFFFF)或文字颜色码(white)来设定这两个值。 var btnOffColor = "white"; // 一般、预设状态或未被选取的按钮 (Button Off) var btnOnColor = "e4e4e4"; // 已被选取或已变更预设状态的按钮 (Button On) //-->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值