在 PyQt5 中创建一个非重叠的 QVideoPlayer 和 PlotWidget

Creating a non-overlapping QVideoPlayer and PlotWidget in PyQt5

我正在尝试在 PyQt5 中创建一个具有媒体(视频)播放器、图表和几个按钮的应用程序。目前,每当我尝试添加视频和图形小部件时,即使使用 QGridLayout,它们也会竞争 space(彼此叠加)。

这是到目前为止的整个文件。重要部分在 'Create video object'、'Create plot' 和 'Create GUI Layout'.

对于让视频播放器占据 window 的顶部以及图表占据下方区域的任何建议?

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QGridLayout, QFileDialog, QVBoxLayout, QHBoxLayout
from pyqtgraph import PlotWidget
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtCore import QUrl
import sys


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.setGeometry(300, 100, 900, 600)

        self.init_gui()
        self.show()

    def init_gui(self):

        # Create media object
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)

        # Create video object
        self.videoWidget = QVideoWidget()

        # Create plot (can't get to size properly)
        self.plotWidget = PlotWidget()

        # Create 'Video' button
        self.videoBtn = QPushButton('Open Video')
        self.videoBtn.clicked.connect(self.open_video)

        # Create 'Event Index' Button
        self.eventIndexBtn = QPushButton('Event Index')
        self.eventIndexBtn.setEnabled(False)
        self.eventIndexBtn.clicked.connect(self.open_event_times)

        # Create 'Time Series' Button
        self.timeSeriesBtn = QPushButton('Time Series')
        self.timeSeriesBtn.setEnabled(False)
        self.timeSeriesBtn.clicked.connect(self.open_time_series)

        # Create 'Prev' Button
        self.prevBtn = QPushButton('Prev')
        self.prevBtn.setEnabled(False)

        # Create 'Next' Button
        self.nextBtn = QPushButton('Next')
        self.nextBtn.setEnabled(False)

        # Create 'Replay' Button
        self.replayBtn = QPushButton('Replay')
        self.replayBtn.setEnabled(False)

        # Create file dialog layout
        fileBoxLayout = QVBoxLayout()
        fileBoxLayout.addWidget(self.videoBtn)
        fileBoxLayout.addWidget(self.eventIndexBtn)
        fileBoxLayout.addWidget(self.timeSeriesBtn)

        # Create controls layout
        controlBoxLayout = QHBoxLayout()
        controlBoxLayout.addWidget(self.prevBtn)
        controlBoxLayout.addWidget(self.nextBtn)
        controlBoxLayout.addWidget(self.replayBtn)

        # Create GUI layout
        GUILayout = QGridLayout()
        GUILayout.addWidget(self.videoWidget, 0, 0, 8, 9)
        GUILayout.addWidget(self.plotWidget, 8, 0, 2, 9)
        GUILayout.addLayout(fileBoxLayout, 10, 0, 2, 3)
        GUILayout.addLayout(controlBoxLayout, 10, 3, 2, 6)

        self.setLayout(GUILayout)
        self.mediaPlayer.setVideoOutput(self.videoWidget)

    def open_video(self):
        video_dialog = QFileDialog(self)
        video_dialog.setNameFilters(["Videos (*.mp4 *.avi *.mov *.flv *.wmv)"])
        video_dialog.selectNameFilter("Videos (*.mp4 *.avi *.mov *.flv *.wmv)")
        video_dialog.exec_()
        video_file_name  = video_dialog.selectedFiles()

        if len(video_file_name) != 0:
            self.eventIndexBtn.setEnabled(True)
            # Load first frame
            self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(video_file_name[0])))
            self.mediaPlayer.setPosition(0)
            self.mediaPlayer.play()
            self.mediaPlayer.pause()

    def open_event_times(self):
        event_times_dialog = QFileDialog(self)
        event_times_dialog.setNameFilters(["Text (*.csv)"])
        event_times_dialog.selectNameFilter("Text (*.csv)")
        event_times_dialog.exec_()
        event_times_file_name = event_times_dialog.selectedFiles()

        if len(event_times_file_name) != 0:
            self.timeSeriesBtn.setEnabled(True)
            self.nextBtn.setEnabled(True)

    def open_time_series(self):
        time_series_dialog = QFileDialog(self)
        time_series_dialog.setNameFilters(["Text (*.csv)"])
        time_series_dialog.selectNameFilter("Text (*.csv)")
        time_series_dialog.exec_()
        time_series_file_name = time_series_dialog.selectedFiles()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

问题是 QVideoWidget 在启动时不必显示任何内容,因此 sizeHint 是 (-1x-1) 使其占据尽可能小的尺寸,从而导致您看到的问题。

一个可能的解决方案是在第 0 行和第 1 行之间建立相同的拉伸因子,没有必要也不应该将比例放在跨度中,考虑到上述解决方案是:

# Create GUI layout
GUILayout = QGridLayout()
GUILayout.addWidget(self.videoWidget, 0, 0, 1, 9)
GUILayout.addWidget(self.plotWidget, 1, 0, 1, 9)
GUILayout.addLayout(fileBoxLayout, 2, 0, 2, 3)
GUILayout.addLayout(controlBoxLayout, 3, 3, 2, 6)
GUILayout.setRowStretch(0, 1)
GUILayout.setRowStretch(1, 1)