本文主要是介绍PyQt5:QMediaplayer,QVideowidget播放视频(3),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
PyQt5:QMediaplayer,QVideowidget播放视频(3)
简介
在 PyQt5:QMediaplayer,QVideowidget播放视频(2)上一篇中完善了界面的布局,快进,慢进。在本篇更新中做了代码做了重构,架构的好坏就另说了,python 没有做过成熟的项目,一直自己写的玩。在本篇中主要更新了UI、播放列表、配置项、媒体文件管理、布局、子控件,还有快进、快退、音量等等一些基础功能。
代码结构
模块架构
文件结构
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2020/9/21 20:52 __pycache__
-a---- 2020/5/18 22:28 761 audio.py
-a---- 2020/5/18 22:23 2008 audio.ui
-a---- 2020/9/22 22:13 379 config.json
-a---- 2020/5/6 23:31 2371 itemWidget.ui
-a---- 2020/9/22 22:15 7805 MediaPlayer.py
-a---- 2020/5/18 23:03 1776 MediaPlayer.pyproj
-a---- 2020/9/21 20:52 9788 MediaPlayer.ui
-a---- 2020/9/21 20:52 8664 ui.py
-a---- 2020/5/18 22:01 2281 ui_audio.py
-a---- 2020/5/14 21:10 5533 ui_url.py
-a---- 2020/5/18 23:03 991 urlWidget.py
-a---- 2020/5/14 21:10 7030 urlWidget.ui
在上图中可以看到,主要分为三个模块,MediaPlayer、audio、urlWidget 三个模块。其中 MediaPlayer为主窗口,主体界面布局、逻辑功能、播放窗口、播放列表都在其中实现。audio模块主要负责音量条。urlWidget模块主要负责网络url弹窗输入。
源码介绍
Audio
在文件结构中可以看到,主要有三个文件。audio.ui,ui_audio.py,audio.py 分别是 UI设计文件,UIpy文件,code文件。
Audio.ui
UI设计文件:
Widget类型,布局全部用UI布局,不使用代码,原则是,尽量少用代码设置,方便后期修改维护。布局时,使用Frame嵌套,方便子控件修改。提高易用性,可读性。
Audio_ui.py
FileName = os.path.basename(sys.argv[0])
FilePath = sys.argv[0].replace(FileName,"")
UiName = FileName.replace(".py",".ui")
UiPath = FilePath +UiName
Ui_pyName = FilePath+"ui_audio.py"
FileFlag = os.path.isfile(Ui_pyName)if FileFlag == 0:sys_cmd = os.popen("pyuic5"+" -o "+Ui_pyName+" "+UiPath)time.sleep(1)
还是采用之前的方法,使用命令转换,在更新UI后,删除之前的 ui_xxx.py文件,下次会自动生成。记得将对应的audio.py 设置为启动文件。然后在切回去。
audio.py
from ui_audio import Ui_Audio
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *class audioWidget(QWidget):def __init__(self):super(audioWidget,self).__init__()global uiui = Ui_Audio()ui.setupUi(self)self.audio = uidef getSlider(self):return self.audio.verticalSliderdef getMuteBtn(self):return self.audio.pushButton
对外接口主要有两个 音量输出,静音输出。
urlWidget
与audio模块相同也是拥有三个对应文件. ui 和 ui.py 不做介绍
urlWidget.ui
urlWidget_ui.py
urlWidget.py
from ui_url import Ui_urlWidget
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *class urlWidget(QWidget):fileInfo_Signle = pyqtSignal(list)def __init__(self):super(urlWidget,self).__init__()global uiui = Ui_urlWidget()ui.setupUi(self)self.url = uiui.pushButton_2.clicked.connect(self.sltConfirm)def getFileInfo(self):return [self.url.lineEdit_url.text(),self.url.lineEdit.text()]def sltConfirm(self):self.fileInfo_Signle.emit([self.url.lineEdit_url.text(),self.url.lineEdit.text()])self.hide()def sltCancel(self):self.hide()
其功能主要是添加网络媒体资源时,提供单独的窗口,有两个输入的LineEidt ,一个是 url 路径,一个 媒体资源名称。
提供了两种方式对外输出urlhe 媒体文件名称。调用接口与信号槽
def getFileInfo(self):return [self.url.lineEdit_url.text(),self.url.lineEdit.text()]
fileInfo_Signle = pyqtSignal(list)def sltConfirm(self):self.fileInfo_Signle.emit([self.url.lineEdit_url.text(),self.url.lineEdit.text()])self.hide()
MediaPlayer
该模块主窗口模块,主要负责逻辑部分即业务部分。还有一些 listwdiget,videowidget 主要功能实现,其实按照设计模式应该也做单独的 模块,主窗口负责调用。
下面介绍MediaPlayer
初始化
init
def __init__(self):super(m_window,self).__init__()self.setupUi(self)self.videoframe = QVideoWidget(self) # videoWidget 初始化self.layout_videoframe.addWidget(self.videoframe) # 布局添加videoWidgetself.player = QMediaPlayer(self) #播放器初始化 -- 只负责播放功能self.player.setVideoOutput(self.videoframe) #设置播放窗体self.playListInit() #播放列表初始化self.connectBind() # 初始化槽函数绑定,适用于全局,以及全流程self.bindPlaylistAnddListWidget() # 绑定播放列表与ListWidgetself.initAudioAndFile() #音频设置初始化self.fileBtnMenuInit() # 文件菜单初始化self.readConfig() #载入配置文件
音频设置初始化,文件添加初始化
#音频设置初始化,文件添加初始化def initAudioAndFile(self):self.urlWidget = urlWidget()self.urlWidget.fileInfo_Signle.connect(self.sltUrlWidget)self.audio = audioWidget()self.audio.getSlider().valueChanged.connect(self.sltSetAudioValue)self.audio.getMuteBtn().clicked.connect(self.sltSetAudioMute)
播放列表初始化
#播放列表初始化 - 声明/定义/播放模式设置def playListInit(self):self.playList = QMediaPlaylist()self.player.setPlaylist(self.playList)self.playList.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)self.player.positionChanged.connect(self.sltShowPlayTime)
文件菜单初始化
#文件按钮绑定菜单/本地文件/网络资源def fileBtnMenuInit(self):btnMenu=QMenu(self)btnMenu.addAction("本地文件")btnMenu.addAction("网络资源")self.pushButton_file.setMenu(btnMenu)btnMenu.triggered.connect(self.sltFile)
全局信号槽
#信号槽绑定函数 -- 主要功能按键 播放/上一个/下一个/音频/文件/设置def connectBind(self):self.pushButton_play.clicked.connect(self.sltPlayState)self.pushButton_befor.clicked.connect(self.sltPlayBefore)self.pushButton_next.clicked.connect(self.sltPlayNext)self.pushButton_audio.clicked.connect(self.sltAudio)self.pushButton_setup.clicked.connect(self.sltSetup)# 设置ListWidget 右键菜单模式self.listWidget_playlist.setContextMenuPolicy(Qt.CustomContextMenu)self.listWidget_playlist.customContextMenuRequested.connect(self.listWidgetRightMenu)
文件添加
按钮初始化
#文件按钮绑定菜单/本地文件/网络资源def fileBtnMenuInit(self):btnMenu=QMenu(self)btnMenu.addAction("本地文件")btnMenu.addAction("网络资源")self.pushButton_file.setMenu(btnMenu)btnMenu.triggered.connect(self.sltFile)
本地资源添加
#添加本地文件def addLoadFile(self):str = QFileDialog.getOpenFileName(self,"选择媒体文件","D:/","video files(*.avi *.mp4 *.wmv)")filePath = str[0]fileName = (filePath.split('/')[-1]).split('.')[0]return [filePath,fileName]
网络资源
#添加网络文件def addNetFile(self):self.urlWidget.show()def sltUrlWidget(self,list):config['playlist'].append({'filepath':list[0],'filename':list[1]})self.addFile(list[0],list[1])
槽函数 -按钮添加文件
#槽函数-添加文件def sltFile(self,action):if action.text() == "本地文件":fileInfo = self.addLoadFile()config['playlist'].append({'filepath':fileInfo[0],'filename':fileInfo[1]})self.addFile(fileInfo[0],fileInfo[1])elif action.text() == "网络资源":self.addNetFile()def addFile(self,filePath,fileName):self.playList.addMedia(QMediaContent(QUrl.fromLocalFile(filePath)))self.createItem(fileName)
音频设置
#音频设置def sltAudio(self):pos = self.pushButton_audio.mapTo(self,QPoint(0,0)) #获取相对主窗口坐标#计算 X ,Yx = pos.x() + self.pushButton_audio.width()/2 - self.audio.width() / 2y = pos.y() - self.audio.height() - 6self.audio.move(x,y)if self.audio.isHidden() == True:self.audio.show()else:self.audio.hide()def sltSetAudioValue(self,value): #设置音量值self.player.setVolume(value)def sltSetAudioMute(self): #设置静音self.player.setMuted(bool(1 - self.player.isMuted()))
播放列表
QMediaPlayList
#播放列表初始化 - 声明/定义/播放模式设置def playListInit(self):self.playList = QMediaPlaylist()self.player.setPlaylist(self.playList) #播放器绑定播放列表self.playList.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) #设置播放模式self.player.positionChanged.connect(self.sltShowPlayTime) #显示播放位置即进度
添加列表文件
#创建QListWidgetItemdef createItem(self,str):self.item = QListWidgetItem(str)self.listWidget_playlist.addItem(self.item)#绑定QPlayList与QListWidget -- 利用playlist与widgetlist 的 index 索引 一一对应即实现绑定def bindPlaylistAnddListWidget(self):self.listWidget_playlist.itemDoubleClicked.connect(self.doublePressPlayMedia)
ListWidget-双击播放
def doublePressPlayMedia(self,item):self.player.stop()self.playList.setCurrentIndex(self.listWidget_playlist.row(item))self.player.play()self.pushButton_play.setText("暂停")
ListWidget-右键菜单
def listWidgetRightMenu(self,point):self.menu = QMenu(self.listWidget_playlist)self.currentItem = self.listWidget_playlist.itemAt(point)play_action = QAction('播放')del_action = QAction('删除')self.menu.addAction(play_action)self.menu.addAction(del_action)play_action.triggered.connect(self.actionPlay)del_action.triggered.connect(self.actionDel)self.menu.exec(QCursor.pos())#右键播放槽函数def actionPlay(self):self.player.stop()self.playList.setCurrentIndex(self.listWidget_playlist.row(self.currentItem))self.player.play()self.pushButton_play.setText("暂停")#右键删除槽函数def actionDel(self):index = self.listWidget_playlist.row(self.currentItem)if index == self.playList.currentIndex():self.player.stop()self.delCurrentIndex(index)def delCurrentIndex(self,index):current = self.playList.currentIndex()if current == index:self.playList.setCurrentIndex(0)self.player.stop()self.playList.removeMedia(index)self.listWidget_playlist.takeItem(index)
播放设置
播放状态设置
def sltPlayState(self):if self.player.state() == QMediaPlayer.StoppedState or self.player.state() == QMediaPlayer.PausedState:self.player.play()self.pushButton_play.setText("暂停")else:self.player.pause()self.pushButton_play.setText("播放")
上一首、下一首
def sltPlayBefore(self):self.player.stop()self.playList.setCurrentIndex((self.playList.currentIndex()-1 < 0) and 0 or self.playList.currentIndex()-1 )self.player.play()def sltPlayNext(self):self.player.stop()self.playList.setCurrentIndex((self.playList.currentIndex() + 1 == self.playList.mediaCount()) and 0 or (self.playList.currentIndex() + 1))self.player.play()
播放进度
#显示播放时长def sltShowPlayTime(self,postion):self.lcdNumber_progress.display(round(postion/1000))
配置文件
配置文件格式
config = {'playlist':[],'playCurrent':{'index':0,'audio':30,'postion':0}}
{"playlist": [{"filepath": "D:/13-\u5c0f\u53ef\u7231/df839b27228fa56f81925bd3a619dc96.mp4","filename": "df839b27228fa56f81925bd3a619dc96"}, {"filepath": "D:/13-\u5c0f\u53ef\u7231/1569254169777.mp4","filename": "1569254169777"}, {"filepath": "D:/13-\u5c0f\u53ef\u7231/1569254169777.mp4","filename": "1569254169777"}],"playCurrent": {"index": 0,"audio": 30,"postion": 2.035}
}
读取配置文件
#配置文件初始化def readConfig(self):file = open("./config.json","r+",encoding='UTF-8')json_str_str = json.load(file)for fileInfo in json_str_str['playlist']:self.addFile(fileInfo["filepath"],fileInfo["filename"])config['playlist'].append({'filepath':fileInfo["filepath"],'filename':fileInfo["filename"]})self.playList.setCurrentIndex(json_str_str["playCurrent"]["index"])self.audio.getSlider().setValue(json_str_str["playCurrent"]["audio"])self.player.setVolume(json_str_str["playCurrent"]["audio"])self.player.setPosition(json_str_str["playCurrent"]["postion"] * 1000)
写入配置文件
#写入配置文件def writeConfig(self):print("Write ConfigFile!")for i in range(0,self.playList.mediaCount()):path = ""if self.playList.media(i).canonicalUrl().isLocalFile():path = self.playList.media(i).canonicalUrl().toLocalFile()else:path = self.playList.media(i).canonicalUrl().toString()config['playlist'][i]["filepath"] = pathconfig['playlist'][i]["filename"] = self.listWidget_playlist.item(i).text()config['playCurrent']['index'] = self.playList.currentIndex()config['playCurrent']['audio'] = self.player.volume()config['playCurrent']['postion'] = self.player.position() / 1000with open("./config.json",'w') as f:json.dump(config,f)#关闭事件,再退出前重写config配置文件def closeEvent(self,event):self.writeConfig()
运行结果
UI布局
音频设置
本地文件导入
网络
下载
Git:https://github.com/WQuit/pyqt-qmediaplayer/tree/qmediaplayer-v0.1
CSDN:https://download.csdn.net/download/u011218356/12885123
后续
下期更新,不围着PyQt5 打转了,最近搭好了OpenCv 框架,将搭配OpenCv 进行 图像处理。
这篇关于PyQt5:QMediaplayer,QVideowidget播放视频(3)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!