Question

I am currently using PyQt4 to develop a video player GUI, and I use QtGui.QSlider to control the progress of video stream. And I am wondering how can I change the slider's value when video is playing?

import sys, os
import xml.etree.ElementTree as ET
from xml.dom import minidom
from PyQt4 import QtCore, QtGui, uic
from PyQt4.phonon import Phonon

class vidplayer(QtGui.QWidget):


def __init__(self,url,xml_url,parent = None):
    self.url = url
    super(vidplayer,self).__init__()
    self.initUI()
    self.getElm_from_XML(xml_url);


def printXMLInfo(self):
    itemlist = self.doc.getElementsByTagName('object')
    for item in itemlist:
        print ("frame-span:"+str(item.attributes['framespan'].value)+
        " Event tag: "+ str(item.attributes['name'].value));
    print(len(itemlist))


def getElm_from_XML(self,xml_url):
    self.doc = minidom.parse(xml_url)
    self.clipList = self.doc.getElementsByTagName('object');
    print("Reading XML done...\n Have read %s elements.\n" %(len(self.clipList)))


def initUI(self):
    ## create widgets
    # phonon video player and media
    self.vp = Phonon.VideoPlayer()
    media = Phonon.MediaSource(self.url)

    # layout components (boxes)
    self.vbox_play = QtGui.QVBoxLayout()
    self.hbox_ctrl_vid = QtGui.QHBoxLayout()
    self.hbox_ctrl_dec = QtGui.QHBoxLayout()
    self.hbox = QtGui.QHBoxLayout()
    self.vbox_control = QtGui.QVBoxLayout()

    # bottons to control
    self.btn_go_prev = QtGui.QPushButton("|<")
    self.btn_go_next = QtGui.QPushButton(">|")
    self.btn_play = QtGui.QPushButton("Play(Pause)")
    self.btn_accept = QtGui.QPushButton("Accept")
    self.btn_reject = QtGui.QPushButton("Reject")

    # slider to interact with videoplayer
    self.sld = QtGui.QSlider(QtCore.Qt.Horizontal,self)
    #self.sld = Phonon.SeekSlider(self)

    ## layout components setup
    self.vbox_control.addStretch(1)
    self.hbox_ctrl_vid.addStretch(1)
    self.hbox_ctrl_dec.addStretch(1)
    self.vbox_play.addStretch(1)
    self.hbox.addStretch(1)
    self.vbox_control.setDirection(QtGui.QBoxLayout.BottomToTop)
    self.vbox_play.setDirection(QtGui.QBoxLayout.BottomToTop)


    ## widgets inits
    self.vp.load(media)
    self.vp.play()

    self.sld.setFocusPolicy(QtCore.Qt.NoFocus)
    self.sld.setRange(1,1000)


    ## widgets assignment
    self.hbox_ctrl_vid.addWidget(self.btn_go_prev)
    self.hbox_ctrl_vid.addWidget(self.btn_play)
    self.hbox_ctrl_vid.addWidget(self.btn_go_next)
    self.hbox_ctrl_dec.addWidget(self.btn_accept)
    self.hbox_ctrl_dec.addWidget(self.btn_reject)

    self.vbox_play.addWidget(self.vp)
    self.vbox_play.addWidget(self.sld)

    self.vbox_control.addLayout(self.hbox_ctrl_dec)
    self.vbox_control.addLayout(self.hbox_ctrl_vid)

    self.hbox.addLayout(self.vbox_play)
    self.hbox.addLayout(self.vbox_control)


    ## main setup and display
    self.setLayout(self.hbox)
    self.setGeometry(300,300,600,400)
    self.setWindowTitle('CCNY_SRI TRECVid iSED UI')
    self.setWindowIcon(QtGui.QIcon('./icon.png'))
    self.show()


    ## connection set up
    self.sld.valueChanged[int].connect(self.sld_changeValue)
    self.vp.finished.connect(self.onReachingFinish)
    self.btn_play.clicked.connect(self.onClicked_play)
    self.btn_go_next.clicked.connect(self.onClicked_nextClip)
    self.btn_go_prev.clicked.connect(self.onClicked_prevClip)


###################### callable functions ##################
def sld_changeValue(self,value):
    totalT = self.vp.totalTime()
    print totalT
    newT = totalT*value/1000
    self.vp.seek(newT)

def onClicked_play(self):
    # BUG: sth wrong with boundary
    if self.vp.isPaused():
        self.vp.play()
        print("resume play")
    elif self.vp.isPlaying():
        self.vp.pause()
        print("pause at",self.sld.value())
    elif self.sld.value()<1000:
        self.vp.play()

def onClicked_nextClip(self):
    print("go next")

def onClicked_prevClip(self):
    print("go prev")

def onClicked_acc(self):
    print("accepted")

def onClicked_rej(self):
    print("rejected")

def onReachingFinish(self):
    self.vp.pause()
    self.vp.stop()


def main():
    app = QtGui.QApplication(sys.argv)
    window = vidplayer(sys.argv[1],sys.argv[2])
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()
Was it helpful?

Solution

There is a dedicated class for that in Phonon: Phonon.SeekSlider:

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        # creating player resource
        self.player = Player()
        # adding controls
        self.sliders = Sliders(self.player)

class Sliders(QtGui.QWidget):
    def __init__(self, player):
        QtGui.QWidget.__init__(self)
        self.seek_slider = Phonon.SeekSlider(player , self)

class Player(Phonon.MediaObject):
    def __init__(self):
        Phonon.MediaObject.__init__(self)
        self.audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self)
        self.path = Phonon.createPath(self, self.audioOutput)

This slider will directly pilot the play and its position will be updated during media playing. But, as that's a drawback I'm looking for a workaround, there is no valueChanged signal :-/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top