PyQt5中MediaPlayer视频无法在指定Layout显示问题排查
问题:PyQt5中QVideoWidget嵌入指定容器有声音无画面
我尝试将MP4视频放入self.ui.videoPlayerWidget组件中,能听到声音但画面无法显示。我原本的做法是创建QVBoxLayout并添加videoWidget,再将布局设置给videoPlayerWidget:
vbox = QVBoxLayout() vbox.setContentsMargins(0,0,0,0) vbox.addWidget(self.videoWidget) self.ui.videoPlayerWidget.setLayout(vbox) # 视频无法显示
当我用self.setCentralWidget(self.videoWidget)替代视频输出设置时能看到画面,但这不是我想要的实现方式。
完整源码
main.py
from PyQt5 import QtWidgets, QtMultimediaWidgets, QtMultimedia, QtCore, QtGui, Qt from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QLineEdit, QComboBox,QVBoxLayout,QHBoxLayout from PyQt5.QtGui import QTransform import sys from ScanCodeMedia import Ui_MainWindow class MainWindow(QMainWindow): def __init__(self,parent=None): QMainWindow.__init__(self,parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) movie_file = QtCore.QUrl.fromLocalFile('./galaxy_background.mp4') vid_media = QtMultimedia.QMediaContent(movie_file) # 创建视频组件 self.videoWidget = QtMultimediaWidgets.QVideoWidget() # self.videoWidget.setGeometry(0, 0, 1920, 1080) vbox = QVBoxLayout() vbox.setContentsMargins(0,0,0,0) vbox.addWidget(self.videoWidget) # 创建媒体播放器 self.mediaPlayer = QtMultimedia.QMediaPlayer(None, QtMultimedia.QMediaPlayer.VideoSurface) self.mediaPlayer.setVideoOutput(self.videoWidget) self.ui.videoPlayerWidget.setLayout(vbox) # 视频无法显示 # 播放列表 self.playlist = QtMultimedia.QMediaPlaylist() self.playlist.setCurrentIndex(0) self.playlist.setPlaybackMode(QtMultimedia.QMediaPlaylist.Loop) self.playlist.addMedia(vid_media) # 关联播放列表到播放器 self.mediaPlayer.setPlaylist(self.playlist) self.mediaPlayer.play() if __name__ == "__main__": app = QApplication(sys.argv) w = MainWindow() w.show() sys.exit(app.exec_())
Ui_MainWindow文件
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'media_player_test.ui' # # Created by: PyQt5 UI code generator 5.15.7 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(1920, 1080) MainWindow.setMinimumSize(QtCore.QSize(1920, 1080)) MainWindow.setMaximumSize(QtCore.QSize(1920, 1080)) MainWindow.setStyleSheet("\n" "\n" "QPushButton{\n" "background-color: transparent;\n" "}") self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setMinimumSize(QtCore.QSize(1920, 1080)) self.centralwidget.setMaximumSize(QtCore.QSize(1920, 1080)) self.centralwidget.setObjectName("centralwidget") self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout.setObjectName("verticalLayout") self.videoPlayerWidget = QtWidgets.QWidget(self.centralwidget) self.videoPlayerWidget.setMinimumSize(QtCore.QSize(1920, 1080)) self.videoPlayerWidget.setMaximumSize(QtCore.QSize(1920, 1080)) self.videoPlayerWidget.setObjectName("videoPlayerWidget") self.horizontalLayout = QtWidgets.QHBoxLayout(self.videoPlayerWidget) self.horizontalLayout.setObjectName("horizontalLayout") self.verticalLayout.addWidget(self.videoPlayerWidget) MainWindow.setCentralWidget(self.centralwidget) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
问题原因
从UI生成代码可以看到,videoPlayerWidget在创建时已经被赋予了一个horizontalLayout布局。你手动调用setLayout(vbox)会覆盖原有布局,但这个操作会导致布局初始化异常,进而使得QVideoWidget无法正确渲染画面(音频不受布局影响所以正常播放)。
解决方案
不需要重新创建布局,直接将videoWidget添加到videoPlayerWidget已有的布局中即可:
- 删除以下代码:
vbox = QVBoxLayout() vbox.setContentsMargins(0,0,0,0) vbox.addWidget(self.videoWidget) self.ui.videoPlayerWidget.setLayout(vbox)
- 替换为:
# 直接使用videoPlayerWidget已有的布局添加视频组件 self.ui.horizontalLayout.addWidget(self.videoWidget) # 或者如果不确定布局名称,也可以用下面的方式获取布局 # self.ui.videoPlayerWidget.layout().addWidget(self.videoWidget)
修改后的__init__方法核心代码如下:
def __init__(self,parent=None): QMainWindow.__init__(self,parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) movie_file = QtCore.QUrl.fromLocalFile('./galaxy_background.mp4') vid_media = QtMultimedia.QMediaContent(movie_file) self.videoWidget = QtMultimediaWidgets.QVideoWidget() self.mediaPlayer = QtMultimedia.QMediaPlayer(None, QtMultimedia.QMediaPlayer.VideoSurface) self.mediaPlayer.setVideoOutput(self.videoWidget) # 关键修改:添加到已有布局 self.ui.horizontalLayout.addWidget(self.videoWidget) self.playlist = QtMultimedia.QMediaPlaylist() self.playlist.setCurrentIndex(0) self.playlist.setPlaybackMode(QtMultimedia.QMediaPlaylist.Loop) self.playlist.addMedia(vid_media) self.mediaPlayer.setPlaylist(self.playlist) self.mediaPlayer.play()
这样修改后,视频画面就能正常显示在videoPlayerWidget容器中,同时保持音频正常播放。
内容的提问来源于stack exchange,提问作者Bireysel Finans
相关产品推荐
相关产品推荐

