在 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)
我正在尝试在 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)