【问题标题】:Exact Position of video in QVideoWidgetQVideoWidget 中视频的确切位置
【发布时间】:2022-08-10 03:42:06
【问题描述】:

我有一个自定义媒体播放器,可以在 PyQt 的帮助下显示图像和视频。媒体播放器由以下python代码实现:

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QVBoxLayout, 
QLabel, \\
QSlider, QStyle, QSizePolicy, QFileDialog
import sys
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtGui import QIcon, QPalette
from PyQt5.QtCore import Qt, QUrl



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

        self.setWindowTitle(\"PyQt5 Media Player\")
        self.setGeometry(350, 100, 700, 500)
        self.setWindowIcon(QIcon(\'player.png\'))

        p =self.palette()
        p.setColor(QPalette.Window, Qt.black)
        self.setPalette(p)

        self.init_ui()


        self.show()


     def init_ui(self):

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


        #create videowidget object

        videowidget = QVideoWidget()


        #create open button
        openBtn = QPushButton(\'Open Video\')
        openBtn.clicked.connect(self.open_file)



        #create button for playing
        self.playBtn = QPushButton()
        self.playBtn.setEnabled(False)
        self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playBtn.clicked.connect(self.play_video)



        #create slider
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0,0)
        self.slider.sliderMoved.connect(self.set_position)



        #create label
        self.label = QLabel()
        self.label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)


        #create hbox layout
        hboxLayout = QHBoxLayout()
        hboxLayout.setContentsMargins(0,0,0,0)

        #set widgets to the hbox layout
        hboxLayout.addWidget(openBtn)
        hboxLayout.addWidget(self.playBtn)
        hboxLayout.addWidget(self.slider)



        #create vbox layout
        vboxLayout = QVBoxLayout()
        vboxLayout.addWidget(videowidget)
        vboxLayout.addLayout(hboxLayout)
        vboxLayout.addWidget(self.label)


        self.setLayout(vboxLayout)

        self.mediaPlayer.setVideoOutput(videowidget)


        #media player signals

        self.mediaPlayer.stateChanged.connect(self.mediastate_changed)
        self.mediaPlayer.positionChanged.connect(self.position_changed)
        self.mediaPlayer.durationChanged.connect(self.duration_changed)


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

        if filename != \'\':
            self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(filename)))
            self.playBtn.setEnabled(True)


    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)
 
            )

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


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


    def set_position(self, position):
         self.mediaPlayer.setPosition(position)


    def handle_errors(self):
        self.playBtn.setEnabled(False)
        self.label.setText(\"Error: \" + self.mediaPlayer.errorString())                          
        app = QApplication(sys.argv)                                                         
        window = Window()                                                     
        sys.exit(app.exec_())    

我想做的是每次播放视频/图像边缘的 x 和 y 坐标,虽然感觉应该很容易,但我真的不知道该怎么做。如图像中所示,每个视频/图像可能具有不同的角位置。我唯一能想到的就是获取视频小部件的尺寸,但这是不对的。

    print(videowidget.height())
    print(videowidget.width())                                 
    print(videowidget.x())
    print(videowidget.y())

  • 我在您的代码中没有看到任何 tkinter - 只有 PyQt - 所以我更改了标签
  • 至于我玩家可能不会给出这类信息。它可能需要挖掘videowidget 的源代码才能得到它。
  • @furas 很抱歉这个错误。非常感谢您的回答。我不会想到的。
  • 很抱歉,但我似乎无法在 pycharm 上找到如何执行此操作,因为 PyQt5 有很多。有人可以帮忙吗?
  • 检查视频小部件videoSurface()nativeResolution()。您可能需要连接到相关信号,因为它可能在播放过程中发生变化并且在启动时无效。

标签: python pyqt qvideowidget


【解决方案1】:

我不确定这是否能准确回答您的问题,但我通过比较视频和小部件的纵横比找到了一种解决方案:

class VideoClickWidget(QVideoWidget):

    def __init__(self):
        QVideoWidget.__init__(self)
    
    def mouseReleaseEvent(self, event):
        widget_width = self.frameGeometry().width()
        widget_height = self.frameGeometry().height()
        widget_ratio = widget_width / widget_height

        video_width = self.mediaObject().metaData("Resolution").width()
        video_height = self.mediaObject().metaData("Resolution").height()
        video_ratio = video_width / video_height

        x, y  = event.pos().x(), event.pos().y()

        # It's wider
        if widget_ratio > video_ratio:
            percentage = video_ratio / widget_ratio
            # we know that video occupies $percentage$ of the widget
            dead_zone = int(np.round(widget_width * ((1 - percentage) / 2)))

            new_x = np.clip(x - dead_zone, 0, widget_width - 2 * dead_zone)

            print(new_x, y)



        else:
            percentage = widget_ratio / video_ratio

            dead_zone = int(np.round(widget_height * ((1 - percentage) / 2)))
            new_y = np.clip(y - dead_zone, 0, widget_height - 2 * dead_zone)

            print(x, new_y)

        
        
        super(QVideoWidget, self).mouseReleaseEvent(event)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-26
    • 1970-01-01
    • 2021-10-20
    • 2012-01-26
    • 2012-11-17
    • 2021-10-16
    相关资源
    最近更新 更多