本文使用PYQT进行视频播放器设计,实现进度条跳转,播放,音量调节,截屏等工作,整个过程踩了一些坑,现将这些东西记录下来,非常感谢各位博主在学习过程中提供的资料参考 ,我也和之前一样将所有设计文件放出来供所有学习者参考。
先把前面的坑踩了,关于前面总是在一些槽函数前面加上@pyqtSlot()的原因,例如使用一个按钮
是因为这个是装饰器,之前我的备注是不加就会执行两次,这个就是原因,编辑一个按钮的槽函数,如下所示
可以看到这个clicked函数其实有两个,所以不加装饰器就会执行两次,但是如果这个函数没有两个还加装饰器就一次也不执行,所以规律就是:
- 函数名只有一个:不加装饰器
- 函数名两个:加装饰器
下面开始正式进行播放器设计:
首先是页面设计,这次的页面相较而言要简单很多,少了很多东西,排版也比较简单,如下所示:
布局如下,图像显示框采用了一个窗口
其中有两个控件需要做提升,提升后类名会变化,变化情况如下所示,提升的原因后面会说,这里简要记录下
提升的方法:对着需要提升的窗口右键,就能看到提升的提示,这里我已经提升了,显示的为取消提升
下面变量定义,将变量修改为熟悉的名字就可以保存为py文件之后使用pyuic生成代码了
生成代码之后第一件事,先安装一个播放器的插件,不然的话代码写好了播放不了,这里推荐使用LAV的播放器,链接如下
LAV Filters 0.76 - 下载 (updatestar.com)
之后我们如果用第二篇文章用的模版来测试页面的话会报错,报错指示到我们生成的py文件里面,如下所示:
原来在提升之后会生成两个引导,这两个需要我们自己去编写,后面会解释提升的原因
先放需要填充的代码,代码如下
myVideoWidget.py
from PyQt5.QtMultimediaWidgets import QVideoWidget
class myVideoWidget(QVideoWidget):
def __init__(self,parent=None):
super(QVideoWidget,self).__init__(parent)
myvideoslider.py
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QSlider
class myVideoSlider(QSlider):
ClickedValue = pyqtSignal(int)
def __init__(self, father):
super().__init__(Qt.Horizontal, father)
def mousePressEvent(self, QMouseEvent): #单击事件
super().mousePressEvent(QMouseEvent)
value = QMouseEvent.localPos().x()
# self.setValue(int(value)/9)
value = round(value/self.width()*self.maximum())
self.ClickedValue.emit(value)
下面开始编写代码,头文件引入这个媒体相关的库
查看初始化函数,这里将QMediaPlayer方法给了我们设计的窗口上,之后其实就是调用这个方法进行视频的一系列操作
但是这样如果运行的话会报错,报错信息如下,我也没看太明白,后面查资料说要提升类,我就提升了,就加入了上面写的代码
这个类也只需要继承下QVideoWidget的属性就行了
这样再次运行就OK了,下面是视频的基本操作了,都使用了槽函数的方法
- 视频打开
- 视频暂停
- 视频开始
- 视频截图
下面是最重要的进度条这个部分,原本我以为这个部门应该一般的,没想到这么复杂
现在可以解释下为什么滑块需要提升了,因为滑块是步进的,就是你再滑块移动的前方点一下,他不会到你点的这个位置,而是往前移动一个,点一下移动一格,就这样,所以为了实现点哪里动到哪里,就需要设置这个,在提升函数中修改,这里我参考了某位博主的资料,使用鼠标单击事件来实现。
之后是在初始化中添加的这个关闭追踪
下面来看下这个滑块的槽函数 ,涉及到滑块移动,鼠标按下松开什么的,有些我也没成功,用了一部分绑定的方法
首先是进度条随视频变化
player.duration()这个函数在这里被广泛使用,因为他是统计视频时间的
调动滑块跳转
按压滑块的时候设置标志以防对视频播放造成影响
完整代码如下所示
# -*- coding: utf-8 -*-
# @Time : 2022/1/29 18:46
# @Author : lx2035
# HELLO LX
import sys
from PyQt5 import QtWidgets
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtGui import *
from video import Ui_Form
from PyQt5.QtCore import *
# from PyQt5.QtCore import pyqtSlot # 引入槽函数
class test(QtWidgets.QMainWindow,Ui_Form):
def __init__(self):
super(test, self).__init__() # 注册初始化事件
self.setupUi(self)
self.setWindowTitle("demo")
self.presses_pressed = False
self.player = QMediaPlayer()
self.player.setVideoOutput(self.widget)
self.player.positionChanged.connect(self.change_prosses)
self.prosses.setTracking(False)
self.prosses.ClickedValue.connect(self.clickedSlider) # 进度条点击跳转
def clickedSlider(self,position):
if self.player.duration() > 0: # 开始播放后才允许进行跳转
video_position = int((position / 100) * self.player.duration())
self.player.setPosition(video_position)
else:
self.prosses.setValue(0)
def on_prosses_sliderMoved(self,position):
self.presses_pressed = True
if self.player.duration() > 0:
video_position = int((position / 100) * self.player.duration())
self.player.setPosition(video_position)
def on_volu_valueChanged(self,position): # 修改声音大小
volume= round(position/self.volu.maximum()*100)
self.player.setVolume(volume)
def change_prosses(self,position): # 改变进度条实现实时跟踪
if not self.presses_pressed: # 进度条被鼠标点击时候不更新
self.vidoeLength = self.player.duration() + 0.1
self.prosses.setValue(round((position / self.vidoeLength) * 100))
def on_prosses_sliderPressed(self):
self.presses_pressed = True
def on_prosses_sliderReleased(self):
self.presses_pressed = False
@pyqtSlot()
def on_btn_chose_clicked(self): # 选择文件
self.player.setMedia(QMediaContent(QtWidgets.QFileDialog.getOpenFileUrl()[0])) # 选取视频文件
self.player.play() # 开始播放
@pyqtSlot()
def on_btn_start_clicked(self): # 开始
self.player.play()
@pyqtSlot()
def on_btn_stop_clicked(self): # 暂停
self.player.pause()
@pyqtSlot()
def on_snip_clicked(self): # 截屏
screen = QGuiApplication.primaryScreen()
cast_jpg = './'+ QDateTime.currentDateTime().toString("yyyy-MM-dd hh-mm-ss-zzz")+'.jpg'
screen.grabWindow(self.widget.winId()).save(cast_jpg)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
calc = test()
calc.show()
sys.exit(app.exec_())
相关的ui文件和py文件开源在我的gitee