PYQT 5 - 我需要制作一个新的 window 视频输出 (QMediaPlayer)

PYQT 5 - I need to make a new window with video output (QMediaPlayer)

我需要为视频输出制作一个新的 window。它应该有一些按钮(稍后我会添加)和一个视频输出。我有主 window 具有音频播放功能,我可以在主 window 上进行视频输出,而不是第二个。 使用 magic.python 的视频检查执行 videopop,这会打开一个新的 window (VideoWindow)。

代码:

文件:main.py

import sys

import magic
# bude obsahovat menu (File, Edit, About,...), Queue, v menu bude historie
from PyQt5.QtCore import QUrl, Qt
from PyQt5.QtGui import QPalette, QColor, QIcon
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import QMainWindow, QApplication, QAction, QFileDialog, QWidget, QLabel, QVBoxLayout, QHBoxLayout, \
    QPushButton, QStyle, QSlider
from ui import UI

class QueueWin(QMainWindow, UI):
    def __init__(self, *args, **kwargs):
        super(QueueWin, self).__init__(*args, **kwargs)
        self.ui(self)

        self.setWindowTitle('MPx')  # nastavi title
        self.setWindowIcon(QIcon('media-player-5.ico'))  # nastavi ikonku

        p = self.palette()
        p.setColor(QPalette.Window, QColor(52, 51, 51))  # nastavi barvu okna
        self.setPalette(p)  # aplikuje barvu

        self.open_file_act.triggered.connect(self.open_file)
        #self.history_act.triggered.connect(self.open_history)
        self.history_act.triggered.connect(self.videopop)
        #self.open_act.triggered.connect(self.clr_history)

        self.mediaPlayer.stateChanged.connect(self.mediastate_changed) #mení ikonku na tlačítku play
        self.mediaPlayer.positionChanged.connect(self.update_position)
        self.mediaPlayer.durationChanged.connect(self.duration_changed)

        self.slider.valueChanged.connect(self.mediaPlayer.setPosition)
        self.audioSlider.valueChanged.connect(self.mediaPlayer.setVolume)

    def open_history (self):
        h = History(self)
        h.show()

    def videopop(self):
        v = VideoWindow(self)
        v.show()

    def credits(self):
        w = Credits(self)
        w.show()

    def open_file(self):
        filename, _ = QFileDialog.getOpenFileName(self, "Open Video")

        if filename != '':
            self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(filename)))
            self.playBtn.setEnabled(True)
            self.mediaPlayer.play()
            mime = magic.Magic(mime=True)  # check zda je soubor video
            videocheck = mime.from_file(filename)

            if videocheck.find('video') != -1:
                self.videopop()
                print('it is video')

    def position_changed(self, position):
        self.slider.setValue(position)

    def duration_changed(self,duration):
        self.slider.setRange(0, duration)

    def update_position(self, position):
        self.slider.blockSignals(True)
        self.slider.setValue(position)
        self.slider.blockSignals(False)

    def play_video(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()

        else:
            self.mediaPlayer.play()

    def mediastate_changed(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))

        else:
            self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))

class VideoWindow(QMainWindow, UI):
    def __init__(self, *args, **kwargs):
        super(VideoWindow, self).__init__(*args, **kwargs)
        self.videoui(self)
        self.setWindowTitle('Video') #nastavi title
        self.setWindowIcon(QIcon('media-player-5.ico')) #nastavi ikonku
        # http://www.iconseeker.com/search-icon/isabi/media-player-5.html   <-- odkaz na ikonku
        self.setGeometry(710, 290, 500, 500) #xMistoOtevreni, yMistoOtevreni, xVelikost, yVelikost
        self.setMinimumSize(400, 400) # xMinimalniVelikost, yMinimalniVelikost
        p = self.palette()
        p.setColor(QPalette.Window, QColor(52, 51, 51)) #nastavi barvu okna
        self.setPalette(p) #aplikuje barvu

class History(QMainWindow):
    def __init__(self, parent=None):
        super(History, self).__init__(parent)
        self.setWindowTitle('Historie')  # nastavi title
        self.setWindowIcon(QIcon('media-player-5.ico'))  # nastavi ikonku
        # http://www.iconseeker.com/search-icon/isabi/media-player-5.html   <-- odkaz na ikonku
        self.setGeometry(710, 290, 500, 200)  # xMistoOtevreni, yMistoOtevreni, xVelikost, yVelikost
        self.setMinimumSize(200, 200)  # xMinimalniVelikost, yMinimalniVelikost

        p = self.palette()
        p.setColor(QPalette.Window, QColor(52, 51, 51))  # nastavi barvu okna
        self.setPalette(p)  # aplikuje barvu

class Credits(QMainWindow):
    def __init__(self, parent=None):
        super(Credits, self).__init__(parent)
        self.setWindowTitle('O programu')  # nastavi title
        self.setWindowIcon(QIcon('media-player-5.ico'))  # nastavi ikonku
        # http://www.iconseeker.com/search-icon/isabi/media-player-5.html   <-- odkaz na ikonku
        self.setGeometry(710, 290, 500, 200)  # xMistoOtevreni, yMistoOtevreni, xVelikost, yVelikost
        self.setMinimumSize(200, 200)  # xMinimalniVelikost, yMinimalniVelikost

        p = self.palette()
        p.setColor(QPalette.Window, QColor(52, 51, 51))  # nastavi barvu okna
        self.setPalette(p)  # aplikuje barvu

        self.label = QLabel('Autor: Tomáš Gabriel, 3.B OAUH<br>Napsáno pomocí Pythonu a PyQt5', self)
        self.label.setStyleSheet("color: yellow")
        self.label.adjustSize()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWin = QueueWin()
    mainWin.show()
    sys.exit(app.exec_())

文件:UI.py

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtMultimedia import QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import QPushButton, QSlider, QStyle, QHBoxLayout, QVBoxLayout, QMenuBar


class UI(object):
    def ui(self, QueueWin):
        QueueWin.setObjectName("QueueWin")
        QueueWin.resize(600, 500)
        _translate = QtCore.QCoreApplication.translate
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.centralWidget = QtWidgets.QWidget(QueueWin)
        #sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
        #sizePolicy.setHorizontalStretch(0)
        #sizePolicy.setVerticalStretch(0)
        #sizePolicy.setHeightForWidth(self.centralWidget.sizePolicy().hasHeightForWidth())
        #self.centralWidget.setSizePolicy(sizePolicy)



        self.openFileBtn = QPushButton("Otevrit soubor...", self.centralWidget)
        self.openFileBtn.clicked.connect(self.open_file)

        self.playBtn = QPushButton(self.centralWidget)  # vytvori tlacitko "play"
        self.playBtn.setEnabled(False)
        self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playBtn.clicked.connect(self.play_video)

        self.slider = QSlider(Qt.Horizontal, self.centralWidget)  # vytvori slider
        self.slider.setRange(0, 0)

        self.audioSlider = QSlider(Qt.Horizontal, self.centralWidget)
        self.audioSlider.setMaximum(100)
        self.audioSlider.setProperty("value", 100)

        QueueWin.setCentralWidget(self.centralWidget)

        # self.queue = QListView(self)
        # self.queue.setAcceptDrops(True)
        # self.queue.setAlternatingRowColors(True)

        self.hbox = QHBoxLayout(self.centralWidget)  # umisti tlacitka, slidery,... do UI
        self.hbox.setContentsMargins(11, 11, 11, 11)
        self.hbox.addWidget(self.openFileBtn)
        self.hbox.addWidget(self.playBtn)
        self.hbox.addWidget(self.slider)
        self.hbox.addWidget(self.audioSlider)

        self.vbox = QVBoxLayout(self.centralWidget)
        #self.vbox.addWidget(videowidget)
        # vbox.addWidget(self.queue)
        self.vbox.addLayout(self.hbox)
        #self.mediaPlayer.setVideoOutput(videowidget)

        #self.mediaPlayer.positionChanged.connect(self.update_position)
        #self.mediaPlayer.durationChanged.connect(self.duration_changed)


        self.menuBar = QMenuBar(QueueWin)
        QueueWin.setMenuBar(self.menuBar)

        self.open = QtWidgets.QMenu(self.menuBar)
        self.open_file_act = QtWidgets.QAction(QueueWin)
        self.open.addAction(self.open_file_act)
        self.open_file_act.setText(_translate("QueueWin", "Otevřít..."))
        self.menuBar.addAction(self.open.menuAction())
        self.open.setTitle(_translate("QueueWin", "Soubor"))

        self.history = QtWidgets.QMenu(self.menuBar)
        self.history_act = QtWidgets.QAction(QueueWin)
        self.history.addAction(self.history_act)
        self.history_act.setText(_translate("QueueWin", "Otevřít historii"))
        self.menuBar.addAction(self.history.menuAction())
        self.history.setTitle(_translate("QueueWin", "Historie"))

        self.historyClr_act = QtWidgets.QAction(QueueWin)
        self.history.addAction(self.historyClr_act)
        self.historyClr_act.setText(_translate("QueueWin", "Vymazat historii"))
        self.historyClr_act.setShortcut('ALT+H')

        #about = self.menuBar.addMenu('Autor')
        #about_act = QAction('O autorovi...', self)
        #about_act.setShortcut('CTRL+A')
        #about_act.triggered.connect(lambda: self.credits())
        #about.addAction(about_act)

        QtCore.QMetaObject.connectSlotsByName(QueueWin)

    def videoui(self, VideoWindow):
        VideoWindow.setObjectName("QueueWin")
        VideoWindow.resize(600, 500)
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.centralWidget = QtWidgets.QWidget(VideoWindow)
        self.videowidget = QVideoWidget(self.centralWidget)
        VideoWindow.setCentralWidget(self.centralWidget)
        self.hbox = QHBoxLayout(self.centralWidget)  # umisti tlacitka, slidery,... do UI
        self.hbox.setContentsMargins(11, 11, 11, 11)
        self.hbox.addWidget(self.videowidget)
        self.vbox = QVBoxLayout(self.centralWidget)
        self.vbox.addLayout(self.hbox)

        QtCore.QMetaObject.connectSlotsByName(VideoWindow)

您没有设置视频输出,VideoWindow 中的 QMediaPlayer 完全没用(因此您可以删除它),而您应该使用为 QueueWin 创建的并设置使用另一个 window.

的 QVideoWidget 进行视频输出

“基本”解决方案如下:

           if videocheck.find('video') != -1:
                videoWindow = VideoWindow(self)
                self.mediaPlayer.setVideoOutput(videoWindow.videowidget)
                videoWindow.show()

不过请注意,您的代码存在一些需要修复的重要问题。

首先,由 pyuic 实用程序生成的文件不应该,永远 被手动修改(阅读如何正确使用这些文件在关于 using Designer) 的官方指南中。

然后,在技术上工作时,不建议创建一个新的 QMainWindow 并将另一个作为父级;每次调用该函数时,您还不断地创建一个 new window,同时您应该 重用 任何现有的 window。一个更合适的方法是在创建主组件时创建子组件 windows,并在需要时显示它们,这样您就可以为单独的视频小部件设置视频输出。
另请注意,您不需要使用外部模块来检查媒体是否确实有视频:只需使用 videoAvailableChanged 信号并显示视频 window 如果参数为 True (您不能在 setMedia() 之后立即检查 isVideoAvailable(),因为该函数是异步的)。

最后,如果您不使用任何 QMainWindow 功能(菜单、工具栏、停靠小部件、状态栏),请改用基本的 QWidget。