39. 媒体播放器
一、音频播放
QSoundEffect
可以用来播放无压缩的音频文件(典型的是 .wav 文件),通过它我们不仅能够以低延迟的方式来播放音频,还能够对音频进行更进一步的操作(比如控制音量)。该类非常适合用来播放交互音效,如弹出框的提示音、游戏音效等。
我们可以在终端中使用 pip
安装 PySide6 模块。默认是从国外的主站上下载,因此,我们可能会遇到网络不好的情况导致下载失败。我们可以在 pip
指令后通过 -i
指定国内镜像源下载。
pip install pyside6 -i https://mirrors.aliyun.com/pypi/simple
国内常用的 pip
下载源列表:
- 阿里云 https://mirrors.aliyun.com/pypi/simple
- 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple
- 清华大学 https://pypi.tuna.tsinghua.edu.cn/simple
- 中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple
创建 QSoundEffect
类的对象方法如下:
QSoundEffect(parent:QObject=None)
QSoundEffect(audioDevice:QAudioDevice, parent:QObject=None)
QSoundEffect
类常用方法如下:
# 实例方法
setSource(url:QUrl) -> None # 设置音频源
source() -> QUrl # 获取音频源
setAudioDevice(device:QAudioDevice) -> None # 设置音频设备
audioDevice() -> QAudioDevice # 获取音频设备
setLoopCount(loopCount:int) -> None # 设置播放次数
loopCount() -> int # 获取播放次数
loopsRemaining() -> int # 获取剩余播放次数
setMuted(muted:bool) -> None # 设置是否静音
isMuted() -> bool # 获取是否静音
setVolume(volume:float) -> None # 设置音量
volume() -> float # 获取音量
isPlaying() -> bool # 获取是否正在播放
isLoaded() -> bool # 获取是否已经加载声源
status() -> QSoundEffet.Status # 获取播放状态
# 槽函数
play() -> None # 开始播放
stop() -> None # 停止播放
# 静态方法
supportedMimeTypes() -> List[str] # 获取支持的类型
QSoundEffect
类常用信号如下:
audioDeviceChanged() # 音频设备发生改变时发射信号
loadedChanged() # 加载状态发生改变时发射信号
loopCountChanged() # 循环次数发生改变时发射信号
loopsRemainingChanged() # 剩余循环次数发生改变时发射信号
mutedChanged() # 静音状态发生改变时发射信号
playingChanged() # 播放状态发生改变时发射信号
sourceChanged() # 音频源发生改变时发射信号
statusChanged() # 状态发生改变时发射信号
volumeChanged() # 音量发生改变时发射信号
用 setSource(url:QUrl)
方法 设置音频源,参数 QUrl
可以是 指向网络的文件,也可以是 本机文件。用 source()
方法 获取音频源 QUrl
。
用 status()
方法 获取当前的播放状态,返回值是枚举类型 QSoundEffect.Status
,可取值如下:
QSoundEffect.Status.Null
QSoundEffect.Status.Loading
QSoundEffect.Status.Ready
QSoundEffect.Status.Error
新建一个 ui.py 文件,用来存放 UI 相关的代码。
from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QLabel, QPushButton, QCheckBox, QSlider
from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QFormLayout
from PySide6.QtCore import Qt
class MyUi:
def setupUi(self, window:QWidget):
window.resize(300, 100) # 1.设置窗口对象大小
vertical_layout = QVBoxLayout(window) # 2.创建一个垂直布局
self.choose_file_label = QLabel("未选择文件") # 3.创建一个标签,用来显示选择的文件,并添加到垂直布局中
vertical_layout.addWidget(self.choose_file_label)
form_layout = QFormLayout() # 4.创建一个表单布局,并添加到垂直布局中
vertical_layout.addLayout(form_layout)
self.volume_slider = QSlider() # 5.创建一个滑块,并添加到表单布局中
form_layout.addRow("音量:", self.volume_slider)
self.volume_slider.setOrientation(Qt.Orientation.Horizontal) # 6.设置滑块的显示方向
self.volume_slider.setRange(0, 100) # 7.设置滑块的范围
self.volume_slider.setValue(80) # 8.设置滑块的值
horizontal_layout = QHBoxLayout() # 9.创建一个水平布局,并添加到垂直布局中
vertical_layout.addLayout(horizontal_layout)
self.choose_file_button = QPushButton("选择音频文件") # 10.创建一个按钮,并添加到水平布局中
horizontal_layout.addWidget(self.choose_file_button)
self.player_button = QPushButton("开始播放")
horizontal_layout.addWidget(self.player_button)
self.player_button.setEnabled(False) # 11.设置按钮为禁用状态
self.silence_checkBox = QCheckBox("是否静音")
horizontal_layout.addWidget(self.silence_checkBox)
新建一个 widget.py 文件,用来存放业务逻辑相关的代码。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QFileDialog
from PySide6.QtCore import QUrl, Qt
from PySide6.QtMultimedia import QSoundEffect
from ui import MyUi
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.__ui = MyUi()
self.__ui.setupUi(self) # 2.初始化页面
self.audio = QSoundEffect() # 3、创建音频播放对象
self.__ui.choose_file_button.clicked.connect(self.choose_file) # 4.按钮被点击后激活信号,选择文件
self.__ui.player_button.clicked.connect(self.player_audio) # 5.按钮被点击后激活信号,播放或暂停音频
self.__ui.volume_slider.valueChanged.connect(self.change_volume) # 6.滑块值改变时激活信号,改变音量
self.__ui.silence_checkBox.checkStateChanged.connect(self.change_silence_state) # 7.复选框状态改变时激活信号,改变静音状态
self.audio.playingChanged.connect(self.audio_playing_changed) # 8.音频播放状态改变时激活信号
def choose_file(self):
# 1.创建文件对话框
file_name, filter = QFileDialog.getOpenFileName(self, caption="选择音频文件", dir="./assets/audio", filter="音频文件(*.wav)")
if file_name == "":
return
message = file_name.split("/")[-1]
self.__ui.choose_file_label.setText(f"你选择了【{message}】音频文件") # 2.选择文件后更改标签的文本
self.audio.setSource(QUrl.fromLocalFile(file_name)) # 3.设置音频播放对象的声源
self.audio.setLoopCount(1) # 4.设置音频播放对象的播放次数
self.change_volume(self.__ui.volume_slider.value()) # 5.设置音量
self.__ui.player_button.setEnabled(True) # 6.启用播放按钮
self.__ui.player_button.setText("开始播放") # 7.重置为开始播放按钮
self.change_silence_state(self.__ui.silence_checkBox.checkState()) # 8.设置是否静音
def player_audio(self):
if self.__ui.player_button.text() == "开始播放":
self.audio.play() # 1.开始播放
self.__ui.player_button.setText("停止播放") # 2.重新设置按键文本为停止播放
elif self.__ui.player_button.text() == "停止播放":
self.audio.stop() # 3.停止播放
self.__ui.player_button.setText("开始播放") # 4.重新设置按键文本为开始播放
def change_volume(self, value:int):
self.audio.setVolume(value / 100) # 1.设置音量
def change_silence_state(self, state:Qt.CheckState):
if state == Qt.CheckState.Checked: # 1.判断是否勾选静音复选框
self.audio.setMuted(True) # 2.如果勾选,则设置静音
elif state == Qt.CheckState.Unchecked:
self.audio.setMuted(False) # 3.如果没有勾选,取消静音
def audio_playing_changed(self):
if self.audio.isPlaying(): # 1.判断音频是否正在播放
self.__ui.player_button.setText("停止播放") # 2.如果音频正在播放,重新设置播放音频按键文本为停止播放
else:
self.__ui.player_button.setText("开始播放") # 3.如果音频播放完成,重新设置播放音频按键文本为开始播放
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
二、媒体播放器
播放器 QMediaPlayer
可以播放音频和视频,它可以直接播放的格式有限。要播放更多格式的音频或视频,例如 mp4 格式的视频文件,需要在本机上安装解码器。
QMediaPlayer
继承自 QObject
,用 QMediaPlayer
定义播放器实例对象的方法如下所示:
QMediaPlayer(parent:QObject=None)
其中 parent
是继承自 QObject
类的实例对象。
QMediaPlayer
类的常用方法:
# 实例方法
sourceDevice() -> QIODevice # 获取音频或视频源QIODevice
setActiveAudioTrack(index:int) -> None # 设置当前的声道
activeAudioTrack() -> int # 获取当前的声道
setActiveVideoTrack(index:int) -> None # 设置当前的视频轨道
activeVideoTrack() -> int # 获取当前的视频轨道
setActiveSubtitleTrack(index:int) -> None # 设置当前的子标题轨道
activeSubtitleTrack() -> int # 获取当前的子标题轨道
playbackRate() -> float # 获取播放速率
isSeekable() -> bool # 获取是否可以定位到某一播放时间
position() -> int # 获取当前的播放时间(毫秒)
setAudioOutput(output:QAudioOutput) -> None # 设置播放音频的设备
setVideoOutput(widget:QVideoWidget) -> None # 设置显示视频的控件
setVideoOutput(item:QGraphcicVideoItem) -> None # 设置显示视频的图项
setLoops(loops:int) -> None # 设置循环播放次数
loops() -> int # 获取循环播放次数
duration() -> int # 获取音频或视频可以播放的总时长(毫秒)
playbackState() -> QMedioPlayer.PlaybackState # 获取播放状态
mediaStatus() -> QMedioPlayer.MediaStatus # 获取播放器所处的状态
error() -> QMediaPlayer.Error # 获取出错原因
errorString() -> str # 获取出错信息
hasAudio() -> bool # 获取多媒体中是否有音频
hasVideo() -> bool # 获取多媒体中是否有视频
bufferProgress() -> float # 获取缓冲百分比,100%时才可以播放
# 槽方法
setSource(source:QUrl, str) -> None # 设置要播放的音频或视频源
setSourceDevice(device:QIODevice, sourceUrl:QUrl=QUrl()) -> None # 设置音频或视频地址QUrl
setPlaybackRate(rate:float) -> None # 设置播放速率
setPosition(position:int) -> None # 设置播放时间(毫秒)
play() -> None # 播放音频或视频
pause() -> None # 暂停播放
stop() -> None # 停止播放并将播放位置重置到开头
QMediaPlayer
类的常用信号:
tracksChanged() # 轨道发生改变时发射信号
activeTracksChanged() # 当轨道发生改变时发射信号
audioOutputChanged() # 音频输出设备发生改变时发射信号
bufferProgressChanged(progress:float) # 缓冲进度发生改变时发射信号
durationChanged(duration:int) # 播放时长发生改变时发射信号
errorChanged() # 出错信息发生改变时发射信号
errorOccurred(error:QMediaPlayer.Error, errorString:str) # 播放出错时发射信号
hasAudioChanged(available:bool) # 可播放音频的状态发生改变时发射信号
hasVideoChanged(videoAvailable:bool) # 可播放视频的状态发生改变时发射信号
loopsChanged() # 播放次数发生改变时发射信号
mediaStatusChanged(status:QMediaPlayer.MediaStatus) # 播放器所在的状态发生改变时发射信号
metaDataChanged() # 播放器元数据发生改变时发射信号
playbackRateChanged(rate:float) # 播放速度发生改变时发射信号
playbackStateChanged(state:QMediaPlayer.PlaybackState) # 播放状态发生改变时发射信号
playingChanged(playing:bool) # 播放状态发生改变时发射信号
positionChanged(position:int) # 播放位置发生改变时发射信号
seekableChanged(seekable:bool) # 可定位播放状态发生改变时发射信号
sourceChanged(media:QUrl) # 音频或视频源发生改变时发射信号
videoOutputChanged() # 关联的视频播放器发生改变时发射信号
要播放音频或视频,首先需要给 QMediaPlayer
设置媒体源。可以用 setSource(source:QUrl)
方法或用 setSourceDevice(device:QIODevice,sourceUrl:QUrl=Default(QUrl))
方法 设置媒体文件,其中 sourceUrl
是可选参数,用于 获取额外的信息。用 source()
和 sourceDevice()
分别 获取媒体源 QUrl
和 QIODevice
。
要显示视频,需要将 QMediaPlayer
与显示视频的控件关联,可以显示视频的控件有 QVideoWidget
、QGraphicsVideoItem
,关联方法分别是 setVideoOutput(widget:QVideoWidget)
和 setVideoOutput(item:QGraphicsVideoItem)
。要播放音频,需要用 setAudioOutput(output:QAudioOutput)
方法 设置音频输出设备。
用 setPlaybackRate(rate:float)
方法 设置播放速率,参数 rate 值为 1.0
表示 正常播放;参数 rate 可以为 负值,表示 回放速率。有些多媒体不支持回放。
用 setLoops(loops:int)
方法 设置循环播放次数,参数 loops 可取值 QMediaPlayer.Loops.Once
(一次)、QMediaPlayer.Loops.Infinite
(无限次)或 其它整数。
用 state()
方法 获取播放状态,返回值为 QMediaPlayer.State
枚举值,可能取值如下:
QMediaPlayer.State.StoppedState
QMediaPlayer.State.PlayingState
QMediaPlayer.State.PausedState
用 playbackState()
方法 获取播放器的播放状态,返回的值是 QMediaPlayer.PlaybackState
枚举值,可能取值如下:
QMediaPlayer.PlaybackState.StoppedState
QMediaPlayer.PlaybackState.PlayingState
QMediaPlayer.PlaybackState.PausedState
用 mediaStatus()
方法 获取播放器所处的状态,返回值是 QMediaPlayer.MediaStatus
枚举值,可能取值如下:
QMediaPlayer.MediaStatus.NoMedia
QMediaPlayer.MediaStatus.LoadingMedia
QMediaPlayer.MediaStatus.LoadedMedia
QMediaPlayer.MediaStatus.StalledMedia
QMediaPlayer.MediaStatus.BufferingMedia
QMediaPlayer.MediaStatus.BufferedMedia
QMediaPlayer.MediaStatus.EndOfMedia
QMediaPlayer.MediaStatus.InvalidMedia
用 error()
方法 获取播放器出错信息,返回值是 QMediaPlayer.Error
枚举值,可能取值如下:
QMediaPlayer.Error.NoError
QMediaPlayer.Error.ResourceError
QMediaPlayer.Error.FormatError
QMediaPlayer.Error.NetworkError
QMediaPlayer.Error.AccessDeniedError
三、音频输出
播放器 QMediaPlayer
需要 关联音频输出设备 才能播放音频。音频输出 需要定义 QAudioOutput
的实例,QAudioOutput
用于连接 QMediaPlayer
与音频输出设备。QAudioOutput
继承自 QObject
。
用 QAudioOutput
创建实例对象的方法如下所示:
QAudioOutput(parent:QObject=None)
QAudioOutput(device:QAudioDevice, parent:QObject=None)
其中 QAudioDevice
是 本机上的音频输入输出设备。
QAudioOutpu
t 类的常用方法如下:
# 实例方法
volume() -> float # 获取音量
isMuted() -> bool # 获取是否静音
device() -> QAudioDevice # 获取音频设备
# 槽方法
setVolume(volume:float) -> None # 设置音量,参数取值范围为0~1
setMuted(muted:bool) -> None # 设置静音状态
setDevice(device:QAudioDevice) -> None # 设置音频设备
QAudioOutput
类的常用信号如下:
deviceChanged() # 音频设备发生改变时发射信号
mutedChanged(muted:bool) # 静音状态发生改变时发送信号
volumeChanged(volume:float) # 音量发生改变时候发射信号
修改 ui.py 文件的内容。
from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QLabel, QPushButton, QCheckBox, QSlider
from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QFormLayout
from PySide6.QtCore import Qt
class MyUi:
def setupUi(self, window:QWidget):
window.resize(300, 100) # 1.设置窗口对象大小
vertical_layout = QVBoxLayout(window) # 2.创建一个垂直布局
self.choose_file_label = QLabel("未选择文件") # 3.创建一个标签,用来显示选择的文件,并添加到垂直布局中
vertical_layout.addWidget(self.choose_file_label)
form_layout = QFormLayout() # 4.创建一个表单布局,并添加到垂直布局中
vertical_layout.addLayout(form_layout)
self.volume_slider = QSlider() # 5.创建一个滑块,并添加到表单布局中
form_layout.addRow("音量:", self.volume_slider)
self.volume_slider.setOrientation(Qt.Orientation.Horizontal) # 6.设置滑块的显示方向
self.volume_slider.setRange(0, 100) # 7.设置滑块的范围
self.volume_slider.setValue(80) # 8.设置滑块的值
horizontal_layout = QHBoxLayout() # 9.创建一个水平布局,并添加到垂直布局中
vertical_layout.addLayout(horizontal_layout)
self.choose_file_button = QPushButton("选择音频文件") # 10.创建一个按钮,并添加到水平布局中
horizontal_layout.addWidget(self.choose_file_button)
self.player_button = QPushButton("开始播放")
horizontal_layout.addWidget(self.player_button)
self.player_button.setEnabled(False) # 11.设置按钮为禁用状态
self.stop_button = QPushButton("停止播放")
horizontal_layout.addWidget(self.stop_button)
self.stop_button.setEnabled(False)
self.silence_checkBox = QCheckBox("是否静音")
horizontal_layout.addWidget(self.silence_checkBox)
修改 widget.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QFileDialog
from PySide6.QtCore import QUrl, Qt
from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
from ui import MyUi
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.__ui = MyUi()
self.__ui.setupUi(self) # 2.初始化页面
self.mediaPlayer = QMediaPlayer() # 3、创建媒体播放器对象
self.audioOutput = QAudioOutput() # 4、创建音频播放对象
self.mediaPlayer.setAudioOutput(self.audioOutput) # 5、设置播放音频的设备
self.__ui.choose_file_button.clicked.connect(self.choose_file) # 6.按钮被点击后激活信号,选择文件
self.__ui.player_button.clicked.connect(self.player_audio) # 7.按钮被点击后激活信号,播放或暂停音频
self.__ui.stop_button.clicked.connect(self.stop_player_audio) # 8.按钮被点击后激活信号,停止播放音频
self.__ui.volume_slider.valueChanged.connect(self.change_volume) # 9.滑块值改变时激活信号,改变音量
self.__ui.silence_checkBox.checkStateChanged.connect(self.change_silence_state) # 10.复选框状态改变时激活信号,改变静音状态
self.mediaPlayer.playbackStateChanged.connect(self.reset_play) # 11、播放状态发生改变时激活信号
def choose_file(self):
# 1.创建文件对话框
file_name, filter = QFileDialog.getOpenFileName(self, caption="选择音频文件", dir="./assets/audio", filter="音频文件(*.mp3 *.wav *.flac)")
if file_name == "":
return
message = file_name.split("/")[-1]
self.__ui.choose_file_label.setText(f"你选择了【{message}】音频文件") # 2.选择文件后更改标签的文本
self.mediaPlayer.setSource(QUrl.fromLocalFile(file_name)) # 3.设置音频播放对象的声源
self.mediaPlayer.setLoops(1) # 4、设置媒体播放器对象的播放次数
self.change_volume(self.__ui.volume_slider.value()) # 5.设置音量
self.__ui.player_button.setEnabled(True) # 6.启用播放按钮和停止按钮
self.__ui.player_button.setText("开始播放") # 7.重置为开始播放按钮
self.change_silence_state(self.__ui.silence_checkBox.checkState()) # 8.设置是否静音
def player_audio(self):
if self.__ui.player_button.text() == "开始播放":
self.mediaPlayer.play() # 1.开始播放
self.__ui.player_button.setText("暂停播放") # 2.重新设置播放音频按键文本为停止播放
self.__ui.stop_button.setEnabled(True) # 3.启用停止播放按键
elif self.__ui.player_button.text() == "暂停播放":
self.mediaPlayer.pause() # 4.暂停播放
self.__ui.player_button.setText("开始播放") # 5.重新设置播放音频按键文本为开始播放
def stop_player_audio(self):
if self.mediaPlayer.playbackState() != QMediaPlayer.PlaybackState.StoppedState: # 1.判断当前是否停止播放
self.mediaPlayer.stop() # 2.停止播放
self.__ui.player_button.setText("开始播放") # 3.重新设置播放音频按键文本为开始播放
self.__ui.stop_button.setEnabled(False) # 4.停止播放后禁用停止播放按键
def change_volume(self, value:int):
self.audioOutput.setVolume(value / 100) # 1.设置音量
def change_silence_state(self, state:Qt.CheckState):
if state == Qt.CheckState.Checked: # 1.判断是否勾选静音复选框
self.audioOutput.setMuted(True) # 2.如果勾选,则设置静音
elif state == Qt.CheckState.Unchecked:
self.audioOutput.setMuted(False) # 3.如果没有勾选,取消静音
def reset_play(self, state:QMediaPlayer.PlaybackState):
if state == QMediaPlayer.PlaybackState.StoppedState: # 1.如果停止播放
self.__ui.player_button.setText("开始播放") # 2.将播放音频按钮设置为开始播放
self.__ui.stop_button.setEnabled(False) # 3.停止播放按钮设置为禁用
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
四、视频输出
播放器 QMediaPlayer
需要 关联视频输出控件 才能播放视频。视频输出 需要用到 视频控件 QVideoWidget
或 视频图项 QGraphicsVideoItem
,其中 QGraphicsVideoItem
作为图项应用于场景中。QVideoWidget
继承自 QWidget
,QGraphicsVideoItem
继承自 QGraphicsObject
。
用 QVideoWidget
和 QGraphicsVideoItem
创建实例对象的方法如下所示:
QVideoWidget(parent:QWidget=None)
QGraphicsVideoItem(parent:QGrapicsItem=None)
QVideoWidget
类的常用方法如下:
# 实例方法
aspectRatioMode() -> Qt.AspectRatioMode # 获取长宽比模式
isFullScreen() -> bool # 获取是否全屏显示
# 槽方法
setAspectRatioMode(mode:Qt.AspectRatioMode) -> None # 设置长宽比模式
setFullScreen(fullScreen:bool) -> None # 设置全屏显示
QVideoWidget
类的常用信号如下:
aspectRatioModeChanged(mode:Qt.AspectRatioMode) # 长宽比模式发生改变时发射信号
fullScreenChanged(fullScreen:bool) # 全屏状态发生改变时发射信号
QGraphicsVideoItem
类的常用方法如下:
setAspectRatioMode(mode:Qt.AspectRatioMode) -> None # 设置长宽比模式
aspectRatioMode() -> Qt.AspectRatioMode # 获取长宽比模式
setOffset(offset:Union[QSize, QSizeF]) -> None # 设置偏移量
offset() -> QPointF # 获取偏移量
setSize(size:Union[QSize, QSizeF]) -> None # 设置尺寸
size() -> QSizeF # 获取尺寸
QGraphicsVideoItem
类的常用方法如下:
nativeSizeChanged(size:QSizeF) # 尺寸发生改变时发射信号
其中,用 setAspectRatioMode(mode:Qt.AspectRatioMode)
方法 设置视频控件所播放视频的长宽比模式,参数 mode
是 Qt.AspectRatioMode
类型的枚举值,可以取值如下:
Qt.AspectRatioMode.IgnoreAspectRatio # 不保持比例关系
Qt.AspectRatioMode.KeepAspectRatio # 保持原比例关系
Qt.AspectRatioMode.KeepAspectRatioByExpanding # 通过扩充保持原比例关系
修改 ui.py 文件的内容。
from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QLabel, QPushButton, QCheckBox, QSlider, QComboBox
from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QFormLayout
from PySide6.QtCore import Qt
from PySide6.QtMultimediaWidgets import QVideoWidget
class MyUi:
def setupUi(self, window:QWidget):
window.resize(800, 600) # 1.设置窗口对象大小
vertical_layout = QVBoxLayout(window) # 2.创建一个垂直布局
self.choose_file_label = QLabel("未选择文件") # 3.创建一个标签,用来显示选择的文件,并添加到垂直布局中
vertical_layout.addWidget(self.choose_file_label)
self.choose_file_label.setFixedHeight(20) # 4.设置标签的高度
self.videoWidget = QVideoWidget() # 5、创建视频播放对象,并添加到布局中
vertical_layout.addWidget(self.videoWidget, 1)
form_layout = QFormLayout() # 6.创建一个表单布局,并添加到垂直布局中
vertical_layout.addLayout(form_layout)
self.volume_slider = QSlider() # 7.创建一个滑块,并添加到表单布局中
form_layout.addRow("音量:", self.volume_slider)
self.volume_slider.setFixedHeight(20) # 8.设置滑块高度
self.volume_slider.setOrientation(Qt.Orientation.Horizontal) # 9.设置滑块的显示方向
self.volume_slider.setRange(0, 100) # 10.设置滑块的范围
self.volume_slider.setValue(80) # 11.设置滑块的值
horizontal_layout = QHBoxLayout() # 12.创建一个水平布局,并添加到垂直布局中
vertical_layout.addLayout(horizontal_layout)
self.choose_file_button = QPushButton("选择文件") # 13.创建一个按钮,并添加到水平布局中
horizontal_layout.addWidget(self.choose_file_button)
self.player_button = QPushButton("开始播放")
horizontal_layout.addWidget(self.player_button)
self.player_button.setEnabled(False) # 14.设置按钮为禁用状态
self.stop_button = QPushButton("停止播放")
horizontal_layout.addWidget(self.stop_button)
self.stop_button.setEnabled(False)
rate_label = QLabel("播放速度:")
horizontal_layout.addWidget(rate_label)
rate_label.setFixedWidth(60)
self.rate_comboBox = QComboBox()
horizontal_layout.addWidget(self.rate_comboBox)
self.rate_comboBox.setFixedWidth(60)
self.rate_comboBox.addItems(["0.5", "0.75", "1.0", "1.25", "1.5", "2.0"])
self.rate_comboBox.setCurrentIndex(2)
self.silence_checkBox = QCheckBox("是否静音")
horizontal_layout.addWidget(self.silence_checkBox)
修改 widget.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QFileDialog
from PySide6.QtCore import QUrl, Qt
from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
from ui import MyUi
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.__ui = MyUi()
self.__ui.setupUi(self) # 2.初始化页面
self.mediaPlayer = QMediaPlayer() # 3、创建媒体播放器对象
self.audioOutput = QAudioOutput() # 4、创建音频播放对象
self.mediaPlayer.setAudioOutput(self.audioOutput) # 5、设置播放音频的设备
self.mediaPlayer.setVideoOutput(self.__ui.videoWidget) # 6、设置播放视频的设备
self.__ui.choose_file_button.clicked.connect(self.choose_file) # 7.按钮被点击后激活信号,选择文件
self.__ui.player_button.clicked.connect(self.player_audio) # 8.按钮被点击后激活信号,播放或暂停音频
self.__ui.stop_button.clicked.connect(self.stop_player_audio) # 9.按钮被点击后激活信号,停止播放音频
self.__ui.volume_slider.valueChanged.connect(self.change_volume) # 10.滑块值改变时激活信号,改变音量
self.__ui.silence_checkBox.checkStateChanged.connect(self.change_silence_state) # 11.复选框状态改变时激活信号,改变静音状态
self.__ui.rate_comboBox.currentTextChanged.connect(self.change_player_rate) # 12.下拉框内容改变时激活信号,改变播放速度
self.mediaPlayer.playbackStateChanged.connect(self.reset_play) # 13、播放状态发生改变时激活信号
def choose_file(self):
# 1.创建文件对话框
file_name, filter = QFileDialog.getOpenFileName(self,
caption="选择音频文件",
dir="./assets/videos",
filter="视频文件(*.mp4 *.avi);;音频文件(*.mp3 *.wav *.flac)"
)
if file_name == "":
return
message = file_name.split("/")[-1]
self.__ui.choose_file_label.setText(f"你选择了【{message}】文件") # 2.选择文件后更改标签的文本
self.mediaPlayer.setSource(QUrl.fromLocalFile(file_name)) # 3.设置音频播放对象的声源
self.mediaPlayer.setLoops(1) # 4、设置媒体播放器对象的播放次数
self.change_volume(self.__ui.volume_slider.value()) # 5.设置音量
self.change_player_rate(self.__ui.rate_comboBox.currentText()) # 6.设置播放速度
self.__ui.player_button.setEnabled(True) # 6.启用播放按钮和停止按钮
self.__ui.player_button.setText("开始播放") # 7.重置为开始播放按钮
self.change_silence_state(self.__ui.silence_checkBox.checkState()) # 8.设置是否静音
def player_audio(self):
if self.__ui.player_button.text() == "开始播放":
self.mediaPlayer.play() # 1.开始播放
self.__ui.player_button.setText("暂停播放") # 2.重新设置播放音频按键文本为停止播放
self.__ui.stop_button.setEnabled(True) # 3.启用停止播放按键
elif self.__ui.player_button.text() == "暂停播放":
self.mediaPlayer.pause() # 4.暂停播放
self.__ui.player_button.setText("开始播放") # 5.重新设置播放音频按键文本为开始播放
def stop_player_audio(self):
if self.mediaPlayer.playbackState() != QMediaPlayer.PlaybackState.StoppedState: # 1.判断当前是否停止播放
self.mediaPlayer.stop() # 2.停止播放
self.__ui.player_button.setText("开始播放") # 3.重新设置播放音频按键文本为开始播放
self.__ui.stop_button.setEnabled(False) # 4.停止播放后禁用停止播放按键
def change_volume(self, value:int):
self.audioOutput.setVolume(value / 100) # 1.设置音量
def change_silence_state(self, state:Qt.CheckState):
if state == Qt.CheckState.Checked: # 1.判断是否勾选静音复选框
self.audioOutput.setMuted(True) # 2.如果勾选,则设置静音
elif state == Qt.CheckState.Unchecked:
self.audioOutput.setMuted(False) # 3.如果没有勾选,取消静音
def change_player_rate(self, text:str):
self.mediaPlayer.setPlaybackRate(float(text)) # 1.设置播放速度
def reset_play(self, state:QMediaPlayer.PlaybackState):
if state == QMediaPlayer.PlaybackState.StoppedState: # 1.如果停止播放
self.__ui.player_button.setText("开始播放") # 2.将播放音频按钮设置为开始播放
self.__ui.stop_button.setEnabled(False) # 3.停止播放按钮设置为禁用
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
五、动画播放
QMovie
用于 播放无声音的静态动画(例如 gif 文件),它在 PySide6.Gui
模块中,需要用 QLabel
的 setMovie(movie:QMovie)
方法与 QLabel
相关联来播放动画。
用 QMovie
类创建播放动画的实例对象的方法如下:
QMoive(parent:QObject=None)
QMoive(filename:str, format:Union[QByteArray, bytes]=Default(QByteArray), parent:QObject=None)
QMoive(device:QIODevice, format:Union[QByteArray, bytes]=Default(QByteArray), parent:QObject=None)
其中 parent
是继承自 QObject
的实例对象,可以用文件名或指向图形动画的 QIODevice
设备来指定动画源;format
用来 指定动画来源的格式,取值类型是 QByteArray
或 bytes
,例如 b'gif'
、b'webp'
,如果不指定格式,系统会自行选择合适的格式。
QMoive
类常用的方法如下:
# 实例方法
setFileName(fileName:str) -> None # 设置动画文件
fileName() -> str # 获取动画文件
setDevice(device:QIODevice) -> None # 设置设备
device() -> QIODevice # 获取设备
setFormat(format:Union[QByteArray, bytes]) -> None # 设置动画格式
format() -> QByteArray # 获取动画格式
setScaledSize(size:QSize) -> None # 设置尺寸
scaledSize() -> QSize # 获取尺寸
speed() -> int # 获取正常播放速度的百分比
setCacheMode(mode:QMovie.CacheMode) -> None # 设置缓冲模式
cacheMode() -> QMovie.CacheMode # 获取缓冲模式
setBackgroundColor(color:Union[QColor, Qt.GlobalColor, str]) -> None # 设置背景颜色
backgroundColor() -> QColor # 获取背景颜色
state() -> QMovie.MovieState # 获取播放状态
currentFrameNumber() -> int # 获取当前帧编号
currentImage() -> QImage # 获取当前帧图片
currentPixmap() -> QPixmap # 获取当前帧图片
frameCount() -> int # 获取总帧数
frameRect() -> QRect # 获取当前帧的矩形
jumpToFrame(frameNumber:int) -> bool # 跳转到指定帧,成功返回True
isValid() -> bool # 获取动画源是否有效
lastErrorString() -> str # 获取最近的错误信息
lastError() -> QImageReader.ImageReaderError # 获取最近的错误信息
loopCount() -> int # 获取循环次数
nextFrameDelay() -> int # 获取播放下一帧的等待时间
# 槽方法
setSpeed(percentSpeed:int) -> None # 设置正常播放速度的百分比
start() -> None # 开始播放动画
stop() -> None # 停止播放动画
setPaused(paused:bool) # 暂停或继续播放动画
jumpToNextFrame() -> bool # 跳转到下一帧,成功返回True
# 静态方法
static supportedFormats() -> list[QByteArray] # 获取支持的动画格式
QMoive
类常用的信号如下:
error(error:QImageReader.ImageReaderError) # 出错时发射信号
finished() # 播放完成时发射信号
frameChanged(frameNumber:int) # 帧发生改变时发射信号
resized(size:QSize) # 调整尺寸时发射信号
started() # 用start()方法开始播放时发射信号
stateChanged(state:QMovie.MovieState) # 播放状态改变时发射信号
updated(rect:QRect) # 更新时发射信号
用 setFileName(fileName:str)
或 setDevice(device:QIODevice)
方法 设置动画源。用 isValid()
方法 获取动画源是否有效。用 setFormat(format:Union[QByteArray,bytes])
方法 设置动画源的格式。
用 start()
方法 开始播放动画,用 stop()
方法 停止播放,用 pause(True)
方法 暂停播放,用 pause(False)
方法 继续播放。用 setSpeed(percentSpeed:int)
方法 设置播放速度,参数是 正常播放速度的百分比值,例如 setSpeed(200)
表示播放速度是原播放速度的 2 倍。
用 setCacheMode(mode:QMovie.CacheMode)
方法 设置播放时是否进行缓存,参数 mode
是 QMovie.CacheMode
类型的枚举值,可以取值如下:
QMovie.CacheMode.CacheNone
QMovie.CacheMode.CacheAll
用 state()
方法可以 获得当前的播放状态,播放状态的返回值可能有以下取值:
QMovie.MovieState.NoRunning
QMovie.MovieState.Running
QMovie.MovieState.Paused
用 lastErrorString()
方法 获取最近出错的信息。用 lastError()
方法 获取出错信息,返回值是 QImageReader.ImageReaderError
的枚举值,可能取值如下:
QImageReader.ImageReaderError.UnknownError
QImageReader.ImageReaderError.FileNotFoundError
QImageReader.ImageReaderError.DeviceError
QImageReader.ImageReaderError.UnsupportedFormatError
QImageReader.ImageReaderError.InvalidDataError
修改 ui.py 文件的内容。
from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QLabel, QToolBar
from PySide6.QtWidgets import QVBoxLayout
from PySide6.QtCore import Qt
from PySide6.QtGui import QAction, QIcon
class MyUi:
def setupUi(self, window:QWidget):
window.resize(800, 600) # 1.设置窗口对象大小
layout = QVBoxLayout(window) # 2.创建一个垂直布局
self.toolBar = QToolBar() # 3.创建一个工具栏,并添加到布局中
layout.addWidget(self.toolBar)
self.toolBar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon) # 4.设置工具栏的显示样式
self.open_file_action = QAction(icon=QIcon("assets/images/1.ico"), text="打开文件") # 5.创建一个动作,并添加到工具栏中
self.toolBar.addAction(self.open_file_action)
self.label = QLabel() # 6.创建一个标签,并添加到布局中
layout.addWidget(self.label)
self.label.setAlignment(Qt.AlignmentFlag.AlignCenter) # 7.设置标签居中
修改 widget.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QFileDialog
from PySide6.QtGui import QMovie
from ui import MyUi
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.__ui = MyUi()
self.__ui.setupUi(self) # 2.初始化页面
self.__ui.open_file_action.triggered.connect(self.open_file) # 4.动作被触发时发射信号
def open_file(self):
# 1.创建文件对话框
file_name, filter = QFileDialog.getOpenFileName(self, caption="选择文件", dir="./assets/images", filter="动图文件(*.gif);;")
if file_name == "":
return
self.movie = QMovie() # 2.创建一个QMovie对象
self.__ui.label.setMovie(self.movie) # 3.设置标签的动画
self.movie.setFileName(file_name) # 4.设置文件名
self.movie.start() # 5.开始播放
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束