You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 06:25:38