QT根据QTAv实现播放器

2023-10-30 00:20
文章标签 实现 qt 播放器 qtav

本文主要是介绍QT根据QTAv实现播放器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

         最近心血来潮突然想自己实现一个播放器的功能,说来过程还有丢丢曲折的,一开始是用

QtMultimedia 来实现的,结果发现需要安装解码器,所以又跑去安装了 K-Lite。然后功能都可以使用了,自己就屁颠屁颠的打包成exe放到另一台没有安装解码器的电脑上去运行,结果不能播放视频- -。最后一通搜索,决定使用QTAv来实现。

        该实现最大的好处就是打包后可以放到另一台不用搭环境的win上正常运行~

先上贴图:

 

大致功能点说明:

        1: 可打开单个文件,多个文件,和遍历文件夹

        2:实现视频文件拖拽到窗口播放,文件拖拽到exe上,直接打开exe和播放文件

        3:记录播放历史,上一次设置的音量

        4:进程最小化,进程最大化,全屏

        5:点击画面可暂停/继续播放

        6:音量slider浮动显示,倍速上拉选

        7: 快进,上一集,暂停/继续播放,下一集,快退,倍速,音量,截图

        8:历史记录可删,双击历史记录播放

        9:视频进度条点击,拖拽跳转

上主程序代码(备注还是挺详细的,毕竟QT我也不熟)~

全部源码下载:

资源下载

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget){ui->setupUi(this);Widgets::registerRenderers();showList = false;timer = new QTimer(this);setObjectName("myWiget");setWindowTitle("播放器");setWindowIcon(QIcon(":/resources/myLogo.ico"));setStyleSheet("#myWiget{border-image:url(:/resources/backImg.png);}");setContentsMargins(0,0,0,0);resize(1280,720);//实例化布局this->vbox = new QVBoxLayout(this);// 上下排列布局vbox->setContentsMargins(0,0,0,0);// **********************************************************************************初始化管理栏***************this->hboxTop = new QHBoxLayout(this);hboxTop->setContentsMargins(0,0,0,0);bar = new QMenuBar();bar->setStyleSheet("margin: 2px 0;width:50px;background-color:rgba(0,0,0,0);color:white;");//透明背景色bar->setAutoFillBackground(false);bar->setMinimumWidth(70);bar->setMaximumWidth(70);// 一级菜单file = bar->addMenu("文件");
//    file->setStyleSheet("background-color:none;");//background-color:green;file->setMinimumWidth(150);file->setAutoFillBackground(false);QList<QAction*> list;QAction *action1=new QAction("打开文件");//QAction(QIcon(":/resource/image/向右箭头.jpg"),"action1");  可显示图标QAction *action2=new QAction("多个文件");QAction *action3=new QAction("打开文件夹");QAction *action4=new QAction("退出");list.append(action1);list.append(action2);list.append(action3);list.append(action4);file->addActions(list);
//    file->addMenu("打开文件");// 下级菜单hboxTop->addWidget(bar);fileVal = new QLabel();fileVal->setStyleSheet("color:white;");fileVal->setText("播放的文件名..........");fileVal->setAlignment(Qt::AlignCenter);// 文字 居中hboxTop->addWidget(fileVal);hideButton = new QPushButton();QPixmap pi = QPixmap(":/resources/hide.png");hideButton->setStyleSheet("background-color:rgba(0,0,0,0);");QIcon btnBack = QIcon(pi);hideButton->setIcon(btnBack);QSize s = QSize(50,25);hideButton->setIconSize(s);hideButton->setMaximumWidth(50);hboxTop->addWidget(hideButton);maxButton = new QPushButton();maxButton->setStyleSheet("background-color:rgba(0,0,0,0);");QPixmap maxpi = QPixmap(":/resources/maxPro.png");QIcon maxbtnBack = QIcon(maxpi);maxButton->setIcon(maxbtnBack);QSize s2 = QSize(50,25);maxButton->setIconSize(s2);maxButton->setMaximumWidth(50);maxButton->setMinimumWidth(50);hboxTop->addWidget(maxButton);closeButton = new QPushButton();
//    closeButton->setStyleSheet("background-color:rgba(0,0,0,0);");QPixmap closepi = QPixmap(":/resources/closePro.png");QIcon closebtnBack = QIcon(closepi);closeButton->setIcon(closebtnBack);QSize s3 = QSize(50,25);closeButton->setIconSize(s3);closeButton->setMaximumWidth(50);closeButton->setMinimumWidth(50);hboxTop->addWidget(closeButton);// **********************************************************************************初始化播放栏***************QWidget* video = new QWidget(this);// 使用wiget来实现大小自适应,QHBoxLayout只能被动的被子组件撑起来video->setContentsMargins(0,0,0,0);this->hboxVideo = new QHBoxLayout(this);hboxVideo->setContentsMargins(0,0,0,0);//实例化媒体播放器及视频播放mOut = new VideoOutput(this);;mPlayer = new AVPlayer(this);mPlayer->setRenderer(mOut);// 默认实时流 连接方式是UDP模式,可能出现丢包,卡顿等,改为tcp模式QHash<QString, QVariant> dict;dict.insert("rtsp_transport", "tcp");mPlayer->setOptionsForFormat(dict);// 开启解码加速mPlayer->setVideoDecoderPriority(QStringList() << "CUDA" << "D3D11" << "DXVA" << "FFmpeg");//"VAAPI"// 新增一个大小随显示屏走的button,且设置为透明的QVBoxLayout* gbox = new QVBoxLayout(mOut->widget());b2 = new QPushButton(this);QPixmap statpi2 = QPixmap(":/resources/stat2.png");QIcon statbtnBack2 = QIcon(statpi2);b2->setIcon(statbtnBack2);b2->setIconSize(QSize(0,0));b2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);b2->setStyleSheet("background-color:rgba(0,0,0,0);");gbox->addWidget(b2);mOut->widget()->setLayout(gbox);hboxVideo->addWidget(mOut->widget());//    hboxVideo->setStretchFactor(videoWidget,1);// 设置该控件为可伸缩,其他控件自动设置为不可伸缩showListButton = new QPushButton(this);showListButton->setMaximumWidth(20);// 设置宽度固定,高度随父组件大小showListButton->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);showListButton->setStyleSheet("border-image:url(:/resources/showList.png);");hboxVideo->addWidget(showListButton);// 历史列表listWidget = new QListWidget(this);
//    listWidget->setStyleSheet("background-color:white;color:black;");listWidget->setMaximumWidth(270);listWidget->setMinimumWidth(270);hboxVideo->addWidget(listWidget);video->setLayout(hboxVideo);// **********************************************************************************初始化视频时间显示栏***************this->hboxVideoTime = new QHBoxLayout(this);hboxVideoTime->setContentsMargins(0,0,0,0);timeLable = new QLabel("00:00:00/00:00:00",this);timeLable->setStyleSheet("color:white;");//margin-bottom:3px;hboxVideoTime->addWidget(timeLable);// **********************************************************************************初始化视频进度条显示栏***************this->hboxVideoIndex = new QHBoxLayout(this);hboxVideoIndex->setContentsMargins(0,0,0,0);timeSlider = new QSlider(this);timeSlider->setContentsMargins(0,0,0,0);// groove表示槽的部分,handle表示滑块,add-page表示未滑过的槽部分,sub-page 表示已滑过的槽部分// 横向展示timeSlider->setOrientation(Qt::Horizontal);// VerticalQString timeSliderStr = "";//"margin:3px;background-color:white;";// 主体样式(样式中注意 horizontal 和 vertical)timeSliderStr += "QSlider{border-color: #bcbcbc;}QSlider::groove:horizontal {border: 1px solid #999999;height: 6px;""left: 5px; right: 5px;}";// 左右留出一定位置,这样进度键才能显示全// 滑块样式timeSliderStr.append("QSlider::handle:horizontal {border: 0px;border-image: url(:/resources/rate.png);""width: 13px;margin: 0px -7px 0px -7px;}");// 已划过槽的样式timeSliderStr.append("QSlider::sub-page:horizontal {background-color:#87CEEB;height: 8px;}");//padding: 2px 0;timeSlider->setStyleSheet(timeSliderStr);timeSlider->installEventFilter(this);// 重载eventFilter事件hboxVideoIndex->addWidget(timeSlider);// **********************************************************************************初始化视频操作显示栏***************this->hboxVideoWork = new QHBoxLayout(this);hboxVideoWork->setContentsMargins(0,0,0,0);// 布局:间隔/组件1/间隔/组件2hboxVideoWork->addStretch();btnLeft = new QLabel("    ");btnLeft->setStyleSheet("margin:0 0 5px 0;background-color:rgba(0,0,0,0);");hboxVideoWork->addWidget(btnLeft);hboxVideoWork->addStretch();backButton = new QPushButton();backButton->setStyleSheet("margin:0 0 5px 0;background-color:rgba(0,0,0,0);");QPixmap backpi = QPixmap(":/resources/back.png");QIcon backbtnBack = QIcon(backpi);backButton->setIcon(backbtnBack);QSize s4 = QSize(85,38);backButton->setIconSize(s4);backButton->setMaximumWidth(90);backButton->setMinimumWidth(90);backButton->setMinimumHeight(50);backButton->setMaximumHeight(50);hboxVideoWork->addWidget(backButton);lastButton = new QPushButton();lastButton->setStyleSheet("margin:0 0 5px 0;background-color:rgba(0,0,0,0);");QPixmap lastpi = QPixmap(":/resources/last.png");QIcon lastbtnBack = QIcon(lastpi);lastButton->setIcon(lastbtnBack);QSize s5 = QSize(85,38);lastButton->setIconSize(s5);lastButton->setMaximumWidth(90);lastButton->setMinimumWidth(90);lastButton->setMinimumHeight(50);lastButton->setMaximumHeight(50);hboxVideoWork->addWidget(lastButton);statButton = new QPushButton();statButton->setStyleSheet("margin:0 0 5px 0;background-color:rgba(0,0,0,0);");QPixmap statpi = QPixmap(":/resources/stat.png");statbtnBack = QIcon(statpi);QPixmap stoppi = QPixmap(":/resources/stop.png");stopbtnBack = QIcon(stoppi);statButton->setIcon(stopbtnBack);QSize s6 = QSize(110,45);statButton->setIconSize(s6);statButton->setMaximumWidth(90);statButton->setMinimumWidth(90);statButton->setMinimumHeight(60);statButton->setMaximumHeight(60);hboxVideoWork->addWidget(statButton);nextButton = new QPushButton();nextButton->setStyleSheet("margin:0 0 5px 0;background-color:rgba(0,0,0,0);");QPixmap nextpi = QPixmap(":/resources/next.png");QIcon nextbtnBack = QIcon(nextpi);nextButton->setIcon(nextbtnBack);QSize s7 = QSize(85,38);nextButton->setIconSize(s7);nextButton->setMaximumWidth(90);nextButton->setMinimumWidth(90);nextButton->setMinimumHeight(50);nextButton->setMaximumHeight(50);hboxVideoWork->addWidget(nextButton);upButton = new QPushButton();upButton->setStyleSheet("margin:0 0 5px 0;background-color:rgba(0,0,0,0);");QPixmap uppi = QPixmap(":/resources/up.png");QIcon upbtnBack = QIcon(uppi);upButton->setIcon(upbtnBack);upButton->setIconSize(QSize(85,38));upButton->setMaximumWidth(90);upButton->setMinimumWidth(90);upButton->setMinimumHeight(50);upButton->setMaximumHeight(50);hboxVideoWork->addWidget(upButton);hboxVideoWork->addStretch();// 倍速按钮boxBtn = new myBoxButton(this);boxBtn->setStyleSheet("margin:0 0 5px 0;background-color:rgba(0,0,0,0);color:white;");QStringList l;l<<"2.0x"<<"1.5x"<<"1.3x"<<"1.0x"<<"0.8x"<<"0.5x"<<"0.3x";boxBtn->addtextItems(l);boxBtn->setText("1.0x");hboxVideoWork->addWidget(boxBtn);// 音量按钮soundButton = new QPushButton();soundButton->setStyleSheet("margin:0 0 5px 0;background-color:rgba(0,0,0,0);");QPixmap soundpi = QPixmap(":/resources/sound.png");soundbtnBack = QIcon(soundpi);QPixmap unsoundpi = QPixmap(":/resources/unsound.png");unsoundbtnBack = QIcon(unsoundpi);soundButton->setIcon(soundbtnBack);soundButton->setIconSize(QSize(45,45));soundButton->setMaximumWidth(50);soundButton->setMinimumWidth(50);soundButton->setMinimumHeight(50);soundButton->setMaximumHeight(50);soundButton->installEventFilter(this);hboxVideoWork->addWidget(soundButton);volumeSlider = new myFloatSlider(this);// groove表示槽的部分,handle表示滑块,add-page表示未滑过的槽部分,sub-page 表示已滑过的槽部分// 纵向展示volumeSlider->setOrientation(Qt::Vertical);
//    volumeSlider->setInvertedAppearance(true);// 反向volumeSlider->installEventFilter(this);// 重载eventFilter事件volumeSlider->setRange(0,100);volumeSlider->setValue(100);volumeSlider->hide();// 最大化按钮tomaxButton = new QPushButton();tomaxButton->setStyleSheet("margin:0 0 5px 0;background-color:rgba(0,0,0,0);");QPixmap toMaxpi = QPixmap(":/resources/max.png");QIcon toMaxbtnBack = QIcon(toMaxpi);tomaxButton->setIcon(toMaxbtnBack);tomaxButton->setIconSize(QSize(70,40));tomaxButton->setMaximumWidth(60);tomaxButton->setMinimumWidth(60);tomaxButton->setMinimumHeight(50);tomaxButton->setMaximumHeight(50);hboxVideoWork->addWidget(tomaxButton);// 截图按钮cutButton = new QPushButton();cutButton->setStyleSheet("margin:0 0 5px 0;background-color:rgba(0,0,0,0);");QPixmap cutpi = QPixmap(":/resources/cut.png");QIcon cutbtnBack = QIcon(cutpi);cutButton->setIcon(cutbtnBack);cutButton->setIconSize(QSize(70,40));cutButton->setMaximumWidth(60);cutButton->setMinimumWidth(60);cutButton->setMinimumHeight(50);cutButton->setMaximumHeight(50);hboxVideoWork->addWidget(cutButton);// 添加一个label,使得btn不贴边btnRight = new QLabel("    ");btnRight->setStyleSheet("margin:0 0 5px 0;background-color:rgba(0,0,0,0);");hboxVideoWork->addWidget(btnRight);
//    hboxVideoWork->setAlignment(Qt::AlignCenter);// 所有组件居中,没有设置间隔的时候,如果要组件居中,可以用这个方式// 从上到下把横向容器放到竖向容器中vbox->addLayout(hboxTop);vbox->addWidget(video);vbox->addLayout(hboxVideoTime);vbox->addLayout(hboxVideoIndex);vbox->addLayout(hboxVideoWork);vbox->setStretchFactor(video,1);// 设置窗口的容器为竖向容器setLayout(this->vbox);connect(showListButton,SIGNAL(clicked()),this,SLOT(showListFc())); //绑定历史列表显隐事件connect(this->listWidget,SIGNAL(itemDoubleClicked(QListWidgetItem*)),this,SLOT(doubleClickPlay(QListWidgetItem*)));//历史列表双击事件connect(this->timer,SIGNAL(timeout()),this,SLOT(updateTime())); //显示已播放时间/总时间connect(this->mPlayer,SIGNAL(durationChanged(qint64)),this,SLOT(setTimeSlider(qint64)));// 总时长变化connect(b2,SIGNAL(clicked()),this,SLOT(playerClick()));// 屏幕点击connect(timeSlider,SIGNAL(valueChanged(int)),this,SLOT(timeChanged(int)));connect(volumeSlider,SIGNAL(valueChanged(int)),this,SLOT(volumeChanged(int)));connect(backButton,SIGNAL(clicked()),this,SLOT(backFc())); //回退事件connect(lastButton,SIGNAL(clicked()),this,SLOT(lastFc())); //上一个视频事件connect(statButton,SIGNAL(clicked()),this,SLOT(statFc())); //暂停/继续事件connect(nextButton,SIGNAL(clicked()),this,SLOT(nextFc())); //下一个视频事件connect(upButton,SIGNAL(clicked()),this,SLOT(upFc())); //快进事件connect(action1,SIGNAL(triggered()),this,SLOT(openFile())); //打开单个文件事件connect(action2,SIGNAL(triggered()),this,SLOT(openFiles())); //打开多个文件事件connect(action3,SIGNAL(triggered()),this,SLOT(openDir())); //打开文件夹事件connect(action4,SIGNAL(triggered()),this,SLOT(closePro())); //退出进程事件connect(soundButton,SIGNAL(clicked()),this,SLOT(openOrCloseVolume())); //开启或关闭音量connect(tomaxButton,SIGNAL(clicked()),this,SLOT(tomax())); //开启或关闭音量connect(hideButton,SIGNAL(clicked()),this,SLOT(hidePro())); //最小化按钮connect(maxButton,SIGNAL(clicked()),this,SLOT(maxPro())); //程序最大化按钮connect(closeButton,SIGNAL(clicked()),this,SLOT(closePro())); //退出进程按钮connect(cutButton,SIGNAL(clicked()),this,SLOT(cutPro())); // 截屏按钮connect(mPlayer->videoCapture(), SIGNAL(imageCaptured(QImage)), SLOT(saveImage(QImage)));//视频图片抓取成功信号connect(boxBtn,SIGNAL(currentTextChanged(QString)),this,SLOT(selectSpeed(QString)));// 倍速切换事件// 初始化历史列表showListFc();// 支持悬浮setAttribute(Qt::WA_Hover);// 支持键盘事件setFocusPolicy(Qt::StrongFocus);// 每0.5s更新一次时间进度timer->start(700);// 接收文件放下事件setAcceptDrops(true);// 初始化和加载文件地址data = new QFile(QApplication::applicationDirPath() + "/data");if(data->open(QIODevice::ReadWrite|QIODevice::Text)){QTextCodec *codec = QTextCodec::codecForName("GBK");QByteArray datas = data->readAll();oldStr = codec->toUnicode(datas);//QString(datas);QJsonParseError jsonError;QJsonDocument jspnDoc = QJsonDocument::fromJson(oldStr.toStdString().c_str(),&jsonError);if (jspnDoc.isEmpty() || (jsonError.error != QJsonParseError::NoError)) {qDebug()<<"文件内容json反转失败!清空文件数据.....";nowVolume = 100;data->close();}else{QJsonObject jsonObj = jspnDoc.object();li = jsonObj.value("list").toArray();nowVolume = jsonObj.value("volume").toInt();volumeSlider->setValue(nowVolume);mPlayer->audio()->setVolume(nowVolume/100.0);for(int i=0;i<li.size();i++){QJsonObject fileInfo = li.at(i).toObject();QString url = fileInfo.value("url").toString();int nameIndex = url.lastIndexOf("/");if(nameIndex == -1){nameIndex = url.lastIndexOf("\\");}QString name = url.mid(nameIndex+1);QListWidgetItem *item = new QListWidgetItem(name,listWidget);item->setData(Qt::ToolTipRole,url);item->setText(name);
//                listWidget->addItem(item);QWidget *w = new QWidget(listWidget);QHBoxLayout *layout=new QHBoxLayout(w);layout->setAlignment(Qt::AlignRight);QPushButton *pushButton=new QPushButton("x",w);pushButton->setMaximumWidth(20);pushButton->setMinimumWidth(20);pushButton->setMinimumHeight(20);pushButton->setMaximumHeight(20);layout->addStretch();layout->addWidget(pushButton);item->setSizeHint(QSize(20,35));w->show();w->setLayout(layout);listWidget->setItemWidget(item,w);widgetItemMap[pushButton] = item;connect(pushButton,SIGNAL(clicked()),this,SLOT(delItem())); //删除项}data->close();}}else{qDebug()<<"创建文件失败!!";}
}Widget::~Widget(){saveData();timer->stop();
//    mPlayer->stop();
//    delete mPlayer;delete ui;
}
void Widget::dropEvent(QDropEvent *e){int first = true;foreach (const QUrl &url, e->mimeData()->urls()){//加载视频文件QString urlStr = url.url();if(first){first = false;mPlayer->play(urlStr);}if(urlStr.endsWith(".mkv") || urlStr.endsWith(".mp4")|| urlStr.endsWith(".mp3") || urlStr.endsWith(".avi")){if(oldStr.contains(urlStr)){continue;}oldStr.append(";"+urlStr);int nameIndex = urlStr.lastIndexOf("/");QString name = urlStr.mid(nameIndex+1);QListWidgetItem *item = new QListWidgetItem(name,this->listWidget);item->setData(Qt::ToolTipRole,urlStr);item->setText(name);fileVal->setText(name);QWidget *w = new QWidget(listWidget);QHBoxLayout *layout=new QHBoxLayout(w);layout->setAlignment(Qt::AlignRight);QPushButton *pushButton=new QPushButton("x",w);pushButton->setMaximumWidth(20);pushButton->setMinimumWidth(20);pushButton->setMinimumHeight(20);pushButton->setMaximumHeight(20);layout->addStretch();layout->addWidget(pushButton);item->setSizeHint(QSize(20,35));w->show();w->setLayout(layout);listWidget->setItemWidget(item,w);widgetItemMap[pushButton] = item;connect(pushButton,SIGNAL(clicked()),this,SLOT(delItem())); //删除项QJsonObject fileInfoObj;fileInfoObj.insert("url",urlStr);li.append(fileInfoObj);}}
}
void Widget::dragEnterEvent(QDragEnterEvent *e){if (e->mimeData()->hasUrls()){e->acceptProposedAction();}
}void Widget::delItem(){QObject* widget = sender();if(widget->inherits("QPushButton")){// 判断类型QPushButton* btn = static_cast<QPushButton*>(widget);QObject* p = btn->parent();QListWidgetItem* item = widgetItemMap[btn];oldStr.replace(item->toolTip(),"");for(int i=0;i<li.size();i++){QJsonValue v = li[i];if(v.toObject().value("url") == item->toolTip()){li.removeAt(i);break;}}QJsonObject dataJson;dataJson.insert("list",li);if(data->open(QIODevice::ReadWrite|QIODevice::Text | QIODevice::Truncate)){QJsonDocument doc(dataJson);QString strRet = QString(doc.toJson(QJsonDocument::Indented));QTextStream ins(data);ins<<strRet<<endl;data->close();}delete btn;delete item;widgetItemMap.remove(btn);}else{qDebug()<<":is not QPushButton=";}
}void Widget::showListFc(){if(!showList){showList = true;listWidget->show();showListButton->setStyleSheet("border-image:url(:/resources/hideList.png);");}else{showList = false;listWidget->hide();showListButton->setStyleSheet("border-image:url(:/resources/showList.png);");}
}void Widget::doubleClickPlay(QListWidgetItem *item){/** 1、获取listWidget中下标位置* 2、设置媒体源、播放选中的歌曲* 3、修改名字* 4、修改图标* 5、定时器启动*/int inde = this->listWidget->currentRow(); //获取当前下标QString url = item->data(Qt::ToolTipRole).toString();fileVal->setText(item->text());mPlayer->play(url);
}void Widget::updateTime(){if(mPlayer->state() == AVPlayer::State::PlayingState || mPlayer->state() == AVPlayer::State::PausedState){// 播放或暂停状态//获取总时间跟当前播放时长qint64 dur = this->mPlayer->duration();qint64 pos = this->mPlayer->position();//实例化两个对象,用来显示QTime durTime(0,0,0);QTime posTime(0,0,0);this->timeLable->setText(posTime.addMSecs(int(pos)).toString("HH:mm:ss") + "/" + durTime.addMSecs(int(dur)).toString("HH:mm:ss"));timeSlider->setValue(pos);}
}void Widget::setTimeSlider(qint64 duration){this->timeSlider->setRange(0,int(duration));
}
void Widget::videoPosChange(qint64 duration){timeSlider->setValue(duration);mPlayer->setPosition(duration);
}
void Widget::timeChanged(int value){
}
void Widget::volumeChanged(int value){volumeSlider->setValue(value);if(mPlayer->state() == AVPlayer::State::PlayingState || mPlayer->state() == AVPlayer::State::PausedState){// 范围:0-1mPlayer->audio()->setVolume(value/100.0);}nowVolume = value;
}bool Widget::eventFilter(QObject *obj, QEvent *e){if (e->type() == QEvent::MouseButtonPress && obj == this->timeSlider){timeSliderClick(obj, e);// 这里不能返回true,不然按住滑块的拖动事件就终止了
//        return true;}else if(e->type() == QEvent::MouseButtonPress && obj == this->volumeSlider){volumeSliderClick(obj, e);}else if(e->type() == QEvent::HoverEnter && obj == this->soundButton){QPushButton* soundBtn = static_cast<QPushButton*>(obj);int x = soundBtn->x();int y = soundBtn->y();
//        if(volumeSlider->isHidden()){volumeSlider->show();volumeSlider->move(x,y-250);volumeSlider->resize(40,270);
//        }inVolumeSlider = false;return false;}else if(e->type() == QEvent::HoverLeave && obj == this->soundButton){// 异步QtConcurrent::run([=](){QThread::sleep(1);// 一秒后确认是否已进入音量滑动条,没有的话则隐藏音量滑动条if(!inVolumeSlider){volumeSlider->hide();}});}else if(e->type() == QEvent::HoverEnter && obj == this->volumeSlider){inVolumeSlider = true;volumeSlider->show();}else if(e->type() == QEvent::HoverLeave && obj == this->volumeSlider){inVolumeSlider = false;volumeSlider->hide();}return QWidget::eventFilter(obj, e);//返回默认的事件过滤器
}
void Widget::paintEvent(QPaintEvent* event){QStyleOption opt;opt.initFrom(this);QPainter p(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}void Widget::volumeSliderClick(QObject *slider, QEvent *event){QSlider* sliderCtrl = static_cast<QSlider*>(slider);QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);if (Qt::LeftButton == mouseEvent->button()){int mxpos = 0;  // 鼠标按下的位置int cxwnd = 0;// 滑槽长度int cxctl = 0;// 滑块宽度// 竖向进度条cxctl = sliderCtrl->minimumSizeHint().height();  // 滑块宽度cxwnd = sliderCtrl->height();if (sliderCtrl->invertedAppearance()){mxpos = mouseEvent->y();}else{mxpos = cxwnd - mouseEvent->y();}// 计算结果,并设置新计算得到的 position 值int scpos = sliderCtrl->minimum() +(int)((sliderCtrl->maximum() - sliderCtrl->minimum()) *((mxpos - cxctl / 2.0) / (cxwnd - cxctl)));if(sliderCtrl->sliderPosition() != scpos){sliderCtrl->setSliderPosition(scpos);mPlayer->audio()->setVolume(scpos/100.0);}if(sliderCtrl->value() <= 0){soundButton->setIcon(unsoundbtnBack);}else{soundButton->setIcon(soundbtnBack);}}
}
void Widget::timeSliderClick(QObject *slider, QEvent *event){QSlider* sliderCtrl = static_cast<QSlider*>(slider);QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);// mouseEvent的x(),y() 可得知鼠标事件指针相对当前窗口的位置; (globalX()、globalY() 返回的是全局坐标)if (Qt::LeftButton == mouseEvent->button()){int mxpos = 0;  // 鼠标按下的位置int cxwnd = 0;// 滑槽长度int cxctl = 0;// 滑块宽度if (Qt::Horizontal == sliderCtrl->orientation()){// 横向进度条cxwnd = sliderCtrl->width();if (sliderCtrl->invertedAppearance()){// 判断进度条是否反转类型(即最大最小值相反)mxpos = cxwnd - mouseEvent->x();}else{mxpos = mouseEvent->x();}}else{// 竖向进度条cxctl = sliderCtrl->minimumSizeHint().height();  // 滑块宽度cxwnd = sliderCtrl->height();if (sliderCtrl->invertedAppearance()){mxpos = mouseEvent->y();}else{mxpos = cxwnd - mouseEvent->y();}}// 计算结果,并设置新计算得到的 position 值int scpos = sliderCtrl->minimum() +(int)((sliderCtrl->maximum() - sliderCtrl->minimum()) *((mxpos - cxctl / 2.0) / (cxwnd - cxctl)));if(sliderCtrl->sliderPosition() != scpos){sliderCtrl->setSliderPosition(scpos);mPlayer->setPosition(scpos);}}
}void Widget::backFc(){// 获取当前播放时长qint64 pos = this->mPlayer->position();long long time = QDateTime::currentDateTime().toMSecsSinceEpoch();// 获取时间戳if(time > leatFreTime + 1500){// 上次快退间隔超过5秒,则一级快退freLevel = 0;}else{freLevel ++;if(freLevel > 2){freLevel = 2;}}if(pos <= 5000+10000*freLevel){// 回退到最初mPlayer->setPosition(0);}else{mPlayer->setPosition(pos - (5000+10000*freLevel));}leatFreTime = time;
}void Widget::lastFc(){int num = listWidget->count();if(num <= 0){return;}QListWidgetItem* item = NULL;if(num == 1){item = listWidget->item(0);}else{int nowFileIndex = -1;QString nowName = fileVal->text();for(int i=0;i<num;i++){QListWidgetItem* pItem = listWidget->item(i);if(pItem->text() == nowName){nowFileIndex = i-1;break;}}if(nowFileIndex == -1 || nowFileIndex >= num){nowFileIndex = 0;}item = listWidget->item(nowFileIndex);}if(item != NULL){fileVal->setText(item->text());item->setSelected(true);}
}
void Widget::statFc(){int state = this->mPlayer->state();if(state == AVPlayer::State::PlayingState){// 暂停,修改图标mPlayer->pause(!mPlayer->isPaused());b2->setIconSize(QSize(150,75));statButton->setIcon(statbtnBack);}else if(state == AVPlayer::State::PausedState){// 继续播放,修改图标mPlayer->pause(!mPlayer->isPaused());b2->setIconSize(QSize(0,0));statButton->setIcon(stopbtnBack);}}
void Widget::openOrCloseVolume(){int num = volumeSlider->value();if(num <= 0){volumeSlider->setValue(oldVolume);soundButton->setIcon(soundbtnBack);}else{oldVolume = num;volumeSlider->setValue(0);soundButton->setIcon(unsoundbtnBack);}
}
void Widget::nextFc(){int num = listWidget->count();if(num <= 0){return;}QListWidgetItem* item = NULL;if(num == 1){item = listWidget->item(0);}else{int nowFileIndex = -1;QString nowName = fileVal->text();for(int i=0;i<num;i++){QListWidgetItem* pItem = listWidget->item(i);if(pItem->text() == nowName){nowFileIndex = i+1;break;}}if(nowFileIndex == -1 || nowFileIndex >= num){nowFileIndex = 0;}item = listWidget->item(nowFileIndex);}if(item != NULL){fileVal->setText(item->text());item->setSelected(true);
//        item->setCheckState(Qt::Checked);//Qt::Unchecked}
}
void Widget::upFc(){// 获取当前播放时长qint64 pos = this->mPlayer->position();// 获取总时长qint64 all = this->mPlayer->duration();long long time = QDateTime::currentDateTime().toMSecsSinceEpoch();// 获取时间戳if(time > leatFreTime + 1500){// 上次快进间隔超过5秒,则一级快退freLevel = 0;}else{freLevel ++;if(freLevel > 2){freLevel = 2;}}if(pos + 5000+10000*freLevel >= all){// 快进到结束mPlayer->setPosition(all);}else{mPlayer->setPosition(pos + (5000+10000*freLevel));}leatFreTime = time;
}
void Widget::openFile(){QString url = QFileDialog::getOpenFileName(this,"选择文件","/","音频(*.mkv *.mp4 *.mp3 *.avi)");// 父组件,标题,初始目录,文件过滤器if(url.isEmpty()){return;}int nameIndex = url.lastIndexOf("/");QString name = url.mid(nameIndex+1);fileVal->setText(name);mPlayer->play(url);if(!oldStr.contains(url)){qDebug()<<"oldStr....."<<oldStr<<";url="<<url;QListWidgetItem *item = new QListWidgetItem(name,this->listWidget);item->setData(Qt::ToolTipRole,url);item->setText(name);QWidget *w = new QWidget(listWidget);QHBoxLayout *layout=new QHBoxLayout(w);layout->setAlignment(Qt::AlignRight);QPushButton *pushButton=new QPushButton("x",w);pushButton->setMaximumWidth(20);pushButton->setMinimumWidth(20);pushButton->setMinimumHeight(20);pushButton->setMaximumHeight(20);layout->addStretch();layout->addWidget(pushButton);item->setSizeHint(QSize(20,35));w->show();w->setLayout(layout);listWidget->setItemWidget(item,w);widgetItemMap[pushButton] = item;connect(pushButton,SIGNAL(clicked()),this,SLOT(delItem())); //删除项
//        listWidget->addItem(item);QJsonObject fileInfo;fileInfo.insert("url",url);li.append(fileInfo);saveData();oldStr.append(";"+url);item->setSelected(true);}}void Widget::saveData(){QJsonObject dataJson;dataJson.insert("list",li);dataJson.insert("volume",nowVolume);if(data->open(QIODevice::ReadWrite|QIODevice::Text | QIODevice::Truncate)){QJsonDocument doc(dataJson);QString strRet = QString(doc.toJson(QJsonDocument::Indented));QTextStream ins(data);ins<<strRet<<endl;data->close();}
}
void Widget::openFiles(){QStringList urlList = QFileDialog::getOpenFileNames(this,"选择文件","/","音频(*.mkv *.mp4 *.mp3 *.avi)");//Image Files(*.jpg *.png);;MP4(*.mp4)if(urlList.size() == 0){return;}for(int i = 0;i < urlList.size();i++){int nameIndex = urlList.at(i).lastIndexOf("/");QString name = urlList.at(i).mid(nameIndex+1);fileVal->setText(name);if(i==0){mPlayer->play(urlList.at(i));}if(!oldStr.contains(urlList.at(i))){oldStr.append(";"+urlList.at(i));QListWidgetItem *item = new QListWidgetItem(name,this->listWidget);item->setData(Qt::ToolTipRole,urlList.at(i));item->setText(name);QWidget *w = new QWidget(listWidget);QHBoxLayout *layout=new QHBoxLayout(w);layout->setAlignment(Qt::AlignRight);QPushButton *pushButton=new QPushButton("x",w);pushButton->setMaximumWidth(20);pushButton->setMinimumWidth(20);pushButton->setMinimumHeight(20);pushButton->setMaximumHeight(20);layout->addStretch();layout->addWidget(pushButton);item->setSizeHint(QSize(20,35));w->show();w->setLayout(layout);listWidget->setItemWidget(item,w);widgetItemMap[pushButton] = item;connect(pushButton,SIGNAL(clicked()),this,SLOT(delItem())); //删除项
//            listWidget->addItem(item);QJsonObject fileInfo;fileInfo.insert("url",urlList.at(i));li.append(fileInfo);saveData();}}
}
void Widget::openDir(){QString dirUrl = QFileDialog::getExistingDirectory(this,"选择文件夹","/");if(dirUrl.isEmpty()){return;}QDir dir;dir.setFilter(QDir::Files | QDir::Hidden | QDir::Dirs);dir.setSorting(QDir::Size | QDir::Reversed);dir.setPath(dirUrl);int oldNum = li.size();readDir(dir);if(li.size() > oldNum){// 数据落地saveData();}
}void Widget::closePro(){QApplication* app;app->quit();
}void Widget::cutPro(){if(mPlayer->state() == AVPlayer::State::PlayingState || mPlayer->state() == AVPlayer::State::PausedState){// 不自动保存mPlayer->videoCapture()->setAutoSave(false);QDir d;if(d.mkpath(QApplication::applicationDirPath()+"/cutData")){mPlayer->videoCapture()->setCaptureDir(QApplication::applicationDirPath()+"/cutData");mPlayer->videoCapture()->capture();}}
}void Widget::saveImage(QImage img){QString timeStr = QDateTime::currentDateTime().toString("yyyyMMddHHmmss");// 100: 质量因数,0~100或-1,100表示大型未压缩img.save(QApplication::applicationDirPath()+"/cutData/"+timeStr+".jpg","JPG",100);
}void Widget::playerClick(){int state = this->mPlayer->state();if(state == AVPlayer::State::PlayingState){// 暂停,修改图标mPlayer->pause(!mPlayer->isPaused());b2->setIconSize(QSize(150,75));statButton->setIcon(statbtnBack);}else if(state == AVPlayer::State::PausedState){// 继续播放,修改图标mPlayer->pause(!mPlayer->isPaused());b2->setIconSize(QSize(0,0));statButton->setIcon(stopbtnBack);}
}void Widget::readDir(QDir dir){QFileInfoList list = dir.entryInfoList();for (int i = 0; i < list.size(); ++i) {if(list.at(i).isDir()){// 目录if(!list.at(i).filePath().endsWith(".")){QDir loadDir(list.at(i).filePath());if(loadDir.exists()){loadDir.setFilter(QDir::Files | QDir::NoSymLinks | QDir::Dirs);readDir(loadDir);}}}else{// 文件QFileInfo fileInfo = list.at(i);if(fileInfo.filePath().endsWith(".mkv") || fileInfo.filePath().endsWith(".mp4")|| fileInfo.filePath().endsWith(".mp3") || fileInfo.filePath().endsWith(".avi")){if(oldStr.contains(fileInfo.filePath())){continue;}oldStr.append(";"+fileInfo.filePath());int nameIndex = fileInfo.filePath().lastIndexOf("/");QString name = fileInfo.filePath().mid(nameIndex+1);QListWidgetItem *item = new QListWidgetItem(name,this->listWidget);item->setData(Qt::ToolTipRole,fileInfo.filePath());item->setText(name);QWidget *w = new QWidget(listWidget);QHBoxLayout *layout=new QHBoxLayout(w);layout->setAlignment(Qt::AlignRight);QPushButton *pushButton=new QPushButton("x",w);pushButton->setMaximumWidth(20);pushButton->setMinimumWidth(20);pushButton->setMinimumHeight(20);pushButton->setMaximumHeight(20);layout->addStretch();layout->addWidget(pushButton);item->setSizeHint(QSize(20,35));w->show();w->setLayout(layout);listWidget->setItemWidget(item,w);widgetItemMap[pushButton] = item;connect(pushButton,SIGNAL(clicked()),this,SLOT(delItem())); //删除项QJsonObject fileInfoObj;fileInfoObj.insert("url",fileInfo.filePath());li.append(fileInfoObj);}
//            qDebug() << qPrintable(QString("%1").arg(fileInfo.size(), 10))<<";;;;;;;;path="<<fileInfo.filePath();}}
}
void Widget::keyPressEvent(QKeyEvent *event){if(event->key()==Qt::Key_Left){if(!event->isAutoRepeat()){backFc();}}if(event->key()==Qt::Key_Right){if(!event->isAutoRepeat()){upFc();}}if(event->key()==Qt::Key_Up){addVolume();}if(event->key()==Qt::Key_Down){subVolume();}if(event->key()==Qt::Key_Escape){fileVal->show();hideButton->show();maxButton->show();closeButton->show();backButton->show();lastButton->show();statButton->show();nextButton->show();upButton->show();tomaxButton->show();timeSlider->show();timeLable->show();soundButton->show();bar->show();btnRight->show();btnLeft->show();boxBtn->show();cutButton->show();}
}void Widget::subVolume(){int num = volumeSlider->value();if(num <= 0){soundButton->setIcon(soundbtnBack);return;}num -= 15;if(num <= 0){num = 0;}nowVolume = num;volumeSlider->setValue(num);mPlayer->audio()->setVolume(num/100.0);
}void Widget::addVolume(){int num = volumeSlider->value();if(num <= 0){soundButton->setIcon(soundbtnBack);}if(num >= 100){return;}num += 15;if(num > 100){num = 100;}nowVolume = num;volumeSlider->setValue(num);mPlayer->audio()->setVolume(num/100.0);
}void Widget::tomax(){setWindowState(Qt::WindowMaximized);fileVal->hide();hideButton->hide();maxButton->hide();closeButton->hide();backButton->hide();lastButton->hide();statButton->hide();nextButton->hide();upButton->hide();tomaxButton->hide();volumeSlider->hide();timeSlider->hide();timeLable->hide();soundButton->hide();bar->hide();btnRight->hide();btnLeft->hide();boxBtn->hide();cutButton->hide();showList = false;listWidget->hide();showListButton->setStyleSheet("border-image:url(:/resources/hideList.png);");
}void Widget::hidePro(){setWindowState(Qt::WindowMinimized);
}void Widget::maxPro(){setWindowState(Qt::WindowMaximized);
}void Widget::filePlay(QString url){if(url.endsWith(".mkv") || url.endsWith(".mp4")|| url.endsWith(".mp3") || url.endsWith(".avi")){int nameIndex = url.lastIndexOf("\\");QString name = url.mid(nameIndex+1);fileVal->setText(name);mPlayer->play(url);if(!oldStr.contains(url) && !oldStr.contains(name)){QListWidgetItem *item = new QListWidgetItem(name,this->listWidget);item->setData(Qt::ToolTipRole,url);item->setText(name);QWidget *w = new QWidget(listWidget);QHBoxLayout *layout=new QHBoxLayout(w);layout->setAlignment(Qt::AlignRight);QPushButton *pushButton=new QPushButton("x",w);pushButton->setMaximumWidth(20);pushButton->setMinimumWidth(20);pushButton->setMinimumHeight(20);pushButton->setMaximumHeight(20);layout->addStretch();layout->addWidget(pushButton);item->setSizeHint(QSize(20,35));w->show();w->setLayout(layout);listWidget->setItemWidget(item,w);widgetItemMap[pushButton] = item;connect(pushButton,SIGNAL(clicked()),this,SLOT(delItem())); //删除项QJsonObject fileInfo;fileInfo.insert("url",url);li.append(fileInfo);saveData();oldStr.append(";"+url);item->setSelected(true);}}
}
void Widget::selectSpeed(QString sp){QString s= sp.replace("x","");speed = s.toDouble();mPlayer->setSpeed(speed);
}

这篇关于QT根据QTAv实现播放器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/304382

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import