我剛開始檢查 QT for Python。我想構建一個以視頻為背景的應用程式。我剛剛花了幾個小時試圖讓它在 QT 中作業,但我無法理解它。我有一個框架self.MainFrame = QtWidgets.QFrame(self.centralwidget)來控制我想要的大小。我想要一個以該幀為中心的視頻,完全填充它。我不希望它周圍有任何條,所以它應該只是視頻(裁剪和縮放)。現在我嘗試使用 QVideoWidget 和 QGraphicsView 來做到這一點,但似乎都不適合我。
這是當前的代碼片段(這絕對是一團糟,我一直在嘗試各種方法來使其正常作業)
self.graphicsView = QtWidgets.QGraphicsView(self.MainFrame)
self.graphicsView.setFocusPolicy(QtCore.Qt.NoFocus)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
self.graphicsView.setSizePolicy(sizePolicy)
file = os.path.join(os.path.dirname(__file__), "small.avi")
self.item = QGraphicsVideoItem()
self.graphiScene = QGraphicsScene(self.graphicsView)
self.graphicsView.setScene(self.graphiScene)
self.player = QMediaPlayer()
sizer = QSizeF(1920.0,1080.0)
self.item.setAspectRatioMode(1)
self.item.setSize(sizer)
self.player.setVideoOutput(self.item)
self.graphiScene.addItem(self.item)
self.graphicsView.show()
self.player.setMedia(QMediaContent(QUrl.fromLocalFile(file))) #.QtMultimedia.QMediaContent(QtCore.
我也想讓這個動態,所以它可以以 1920x1080 和 1080x1920 方向顯示并且仍然具有相同的東西(觀察不同的作物和可見部分)
我真的很感激這方面的任何幫助,我覺得我正在失去理智,干杯
PS:我確實看到有一種方法可以裁剪和放大 QT 4 或 smth,不幸的是,它似乎被洗掉了。
uj5u.com熱心網友回復:
當一個小部件簡單地使用父級創建時,它不會自行調整大小(這是布局管理器所做的)。
此外,設定大小策略完全沒有用,因為這些策略僅在布局管理已添加到其中的小部件時才考慮。
為了實作這一點,您必須顯式設定小部件幾何,這通常通過覆寫resizeEvent父級的來完成。
之后,您還需要確保視圖顯示正確的內容,這是通過fitInView()以正確的縱橫比呼叫來實作的:對于您需要的(裁剪),值為KeepAspectRatioByExpanding.
最后,您可能希望以視窗為中心顯示視頻,因此您還需要呼叫centerOn().
為了簡化事情,我建議將中心小部件(在您的情況下為 QFrame)子類化并在其中實作“視頻背景”。
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtMultimedia import *
from PyQt5.QtMultimediaWidgets import *
class FrameWithVideo(QFrame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.background = QGraphicsView(self)
self.background.setBackgroundBrush(Qt.black)
self.background.setFrameShape(0) # no borders
self.background.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.background.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.player = QMediaPlayer()
# for Qt6 you can use self.player.setActiveAudioTrack(-1)
# but in reality you should probably use a video-only file
self.player.setMuted(True)
scene = QGraphicsScene()
self.background.setScene(scene)
self.videoItem = QGraphicsVideoItem()
scene.addItem(self.videoItem)
self.player.setVideoOutput(self.videoItem)
# Qt5 requires a playlist to play content in loop;
# for Qt6 you can use QMediaPlayer.setLoops(-1)
playlist = QMediaPlaylist(self)
playlist.setPlaybackMode(playlist.Loop)
playlist.addMedia(QMediaContent(QUrl.fromLocalFile('/tmp/Armonatrix.mp4')))
self.player.setMedia(QMediaContent(playlist))
self.videoItem.nativeSizeChanged.connect(self.resizeBackground)
def resizeBackground(self):
# ensure that the view is always below any other child
self.background.lower()
# make the view as big as the parent
self.background.resize(self.size())
# resize the item to the video size
self.videoItem.setSize(self.videoItem.nativeSize())
# fit the whole viewable area to the item and crop exceeding margins
self.background.fitInView(
self.videoItem, Qt.KeepAspectRatioByExpanding)
# scroll the view to the center of the item
self.background.centerOn(self.videoItem)
def hideEvent(self, event):
super().hideEvent(event)
self.player.pause()
def showEvent(self, event):
super().showEvent(event)
self.resizeBackground()
self.player.play()
def resizeEvent(self, event):
super().resizeEvent(event)
self.resizeBackground()
class Test(QMainWindow):
def __init__(self):
super().__init__()
self.mainFrame = FrameWithVideo()
self.setCentralWidget(self.mainFrame)
layout = QGridLayout(self.mainFrame)
for r in range(4):
for c in range(4):
layout.addWidget(QPushButton('{} {}'.format(r 1, c 1)), r, c)
def sizeHint(self):
return QApplication.primaryScreen().size() * 2 / 3
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Test()
w.show()
sys.exit(app.exec())
請注意,如果源視頻具有高解析度(720p 或更高),您應該考慮resizeBackground使用設定為的 QTimer 延遲呼叫singleShot:大多數現代系統使用不透明調整大小,這意味著當用戶調整視窗大小時視窗的內容會動態更新; 布局管理要求很高,并且應該始終具有優先權,因為函式呼叫resizeBackground可能會暫時阻止這些計算,輕微的延遲可能會以一些可見的視頻調整大小問題為代價來提高性能。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/520152.html
