如何在Qt for Python中让视频适配组件尺寸
Qt for Python实现视频填满框架(裁剪式缩放+横竖屏适配)
直接上可运行的完整实现代码,解决你要的视频居中填满框架、无黑边、横竖屏动态适配的需求:
import os from PyQt5 import QtWidgets, QtCore, QtMultimedia, QtMultimediaWidgets from PyQt5.QtCore import Qt, QSizeF class VideoBackgroundWindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.centralwidget = QtWidgets.QWidget(self) self.setCentralWidget(self.centralwidget) # 你的目标框架,控制视频显示尺寸 self.MainFrame = QtWidgets.QFrame(self.centralwidget) self.MainFrame.setStyleSheet("background-color: black;") # 黑底避免视频加载前空白 # 用布局让MainFrame铺满中央部件,也可手动设置geometry layout = QtWidgets.QVBoxLayout(self.centralwidget) layout.addWidget(self.MainFrame) layout.setContentsMargins(0,0,0,0) # 初始化视频相关组件 self.graphicsView = QtWidgets.QGraphicsView(self.MainFrame) self.graphicsView.setFocusPolicy(Qt.NoFocus) # 去掉滚动条,铺满MainFrame self.graphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphicsView.setGeometry(self.MainFrame.rect()) self.graphiScene = QtWidgets.QGraphicsScene(self.graphicsView) self.graphicsView.setScene(self.graphiScene) # 设置场景对齐方式为居中 self.graphicsView.setAlignment(Qt.AlignCenter) self.item = QtMultimediaWidgets.QGraphicsVideoItem() # 关键:设置比例模式为按比例扩展,超出部分裁剪 self.item.setAspectRatioMode(Qt.KeepAspectRatioByExpanding) self.graphiScene.addItem(self.item) # 初始化媒体播放器 self.player = QtMultimedia.QMediaPlayer(None, QtMultimedia.QMediaPlayer.VideoSurface) self.player.setVideoOutput(self.item) # 加载本地视频文件 file_path = os.path.join(os.path.dirname(__file__), "small.avi") self.player.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(file_path))) self.player.play() def resizeEvent(self, event): super().resizeEvent(event) # 每次窗口/框架大小变化时,调整视频显示 self.adjust_video_display() def adjust_video_display(self): # 获取MainFrame的当前尺寸 frame_rect = self.MainFrame.rect() frame_size = QSizeF(frame_rect.width(), frame_rect.height()) # 让GraphicsView铺满MainFrame self.graphicsView.setGeometry(frame_rect) # 更新场景大小为框架大小 self.graphiScene.setSceneRect(0, 0, frame_size.width(), frame_size.height()) if self.player.videoSurface().surfaceFormat().size().isEmpty(): return # 视频未加载时跳过 # 获取视频原生尺寸 video_size = QSizeF(self.player.videoSurface().surfaceFormat().size()) # 计算缩放比例:取宽/高比例中较大的那个,确保视频填满框架 scale_ratio = max(frame_size.width() / video_size.width(), frame_size.height() / video_size.height()) # 计算缩放后的视频尺寸 scaled_video_size = video_size * scale_ratio # 设置视频项的大小 self.item.setSize(scaled_video_size) # 让视频项居中显示(超出部分会被GraphicsView裁剪) self.item.setPos( (frame_size.width() - scaled_video_size.width()) / 2, (frame_size.height() - scaled_video_size.height()) / 2 ) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) window = VideoBackgroundWindow() window.show() # 测试横竖屏切换可取消注释 # window.resize(1920, 1080) # window.resize(1080, 1920) sys.exit(app.exec_())
关键要点说明
- 比例模式设置:用
Qt.KeepAspectRatioByExpanding替代你之前的1(对应Qt.KeepAspectRatio),这个模式会让视频按原比例缩放,直到完全覆盖框架,超出部分自动被裁剪,完美实现无黑边填满的需求。 - 动态适配逻辑:重写
resizeEvent,每次框架大小变化时重新计算视频的缩放比例和位置,确保无论横竖屏切换,视频始终居中填满框架。 - 视图设置:关闭滚动条、设置视图铺满框架、场景对齐居中,避免多余的空白或滚动区域。
- 视频加载判断:跳过视频未加载完成时的尺寸计算,避免报错。
解决你之前的问题
你之前的代码手动固定了视频项的尺寸,并且用了错误的比例模式,导致无法填满框架。现在的实现完全动态适配框架尺寸,自动处理横竖屏的裁剪区域变化。
内容的提问来源于stack exchange,提问作者Furry
相关产品推荐
相关产品推荐

