我正在尝试在PyQt5中创建一个具有媒体(视频)播放器,图形和一些按钮的应用。当前,无论何时我尝试添加视频和图形小部件,即使使用QGridLayout,它们也会争夺空间(彼此叠加)。
这里是到目前为止的整个文件。重要部分位于“创建视频对象”,“创建图”和“创建GUI布局”下。
关于让视频播放器占据窗口顶部和图形占据下方区域的任何建议?
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)