最近研究了Python的两个GUI包,Tkinter和PyQT。这两个GUI包的底层分别是Tcl/Tk和QT。相比之下,我觉得PyQT使用起来更加方便,功能也相对丰富。这一篇用PyQT实现一个视频播放器,并借此来说明PyQT的基本用法。

视频播放器

先把已经完成的代码放出来。代码基于Python 3.5:

import time
import sysfrom PyQt4 import QtGui, QtCore
from PyQt4.phonon import Phononclass PollTimeThread(QtCore.QThread):"""This thread works as a timer."""update = QtCore.pyqtSignal()def __init__(self, parent):super(PollTimeThread, self).__init__(parent)def run(self):while True:time.sleep(1)if self.isRunning():# emit signalself.update.emit()else:returnclass Window(QtGui.QWidget):def __init__(self):QtGui.QWidget.__init__(self)# mediaself.media = Phonon.MediaObject(self)self.media.stateChanged.connect(self.handleStateChanged)self.video = Phonon.VideoWidget(self)self.video.setMinimumSize(200, 200)self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self)Phonon.createPath(self.media, self.audio)Phonon.createPath(self.media, self.video)# control buttonself.button = QtGui.QPushButton('选择文件', self)self.button.clicked.connect(self.handleButton)# for display of time lapseself.info = QtGui.QLabel(self)# layoutlayout = QtGui.QGridLayout(self)layout.addWidget(self.video, 1, 1, 3, 3)layout.addWidget(self.info, 4, 1, 1, 3)layout.addWidget(self.button, 5, 1, 1, 3)# signal-slot, for time lapseself.thread = PollTimeThread(self)self.thread.update.connect(self.update)def update(self):# slotlapse = self.media.currentTime()/1000.0self.info.setText("%4.2f 秒" % lapse)def startPlay(self):if self.path:self.media.setCurrentSource(Phonon.MediaSource(self.path))# use a thread as a timerself.thread = PollTimeThread(self)self.thread.update.connect(self.update)self.thread.start()self.media.play()def handleButton(self):if self.media.state() == Phonon.PlayingState:self.media.stop()self.thread.terminate()else:self.path = QtGui.QFileDialog.getOpenFileName(self, self.button.text())self.startPlay()def handleStateChanged(self, newstate, oldstate):if newstate == Phonon.PlayingState:self.button.setText('停止')elif (newstate != Phonon.LoadingState andnewstate != Phonon.BufferingState):self.button.setText('选择文件')if newstate == Phonon.ErrorState:source = self.media.currentSource().fileName()print ('错误:不能播放:', source.toLocal8Bit().data())print ('  %s' % self.media.errorString().toLocal8Bit().data())if __name__ == '__main__':app = QtGui.QApplication(sys.argv)app.setApplicationName('视频播放')window = Window()window.show()sys.exit(app.exec_())

代码实现了一个有GUI窗口的应用,用来播放视频文件。视频播放利用了PyQT中的Phonon模块。此外,还有一个进程每隔一秒发出一个信号。窗口在接收到信号后,更新视频播放的时间。这个应用的效果如下:

测试运行环境为Mac OSX El Capitan。

视图部分

写完这个代码之后,我发现这个代码虽然简单,但涉及了几个重要机制,可以用PyQT的练习题。下面对代码进行一些简要的说明,首先是主程序部分:

app = QtGui.QApplication(sys.argv)
...
window = Window()
window.show()
sys.exit(app.exec_())

在PyQT程序中,QApplication是最上层的对象,指代整个GUI应用。我们在程序的一开始创建了一个应用对象,在程序最后调用exec_()来运行这个应用。sys.exit()用来要求应用的主循环结束后干净地退出程序。PyQT程序的开始和结尾都是类似的固定套路。关键就在于其间定义的QWidget对象。

我们自定义的Window类继承自QWidget。其实QWidget是所有用户界面对象的基类,并不单单指代一个窗口。表格、输入框、按钮都继承自QWidget。在一个Window对象中,我们还组合有QPushButton和QLabel这样的对象,分别代表一个按钮和一个文本框。它们通过QGridLayout的方式,布局在Window的界面上,即下面一部分代码:

# layout
layout = QtGui.QGridLayout(self)
...
layout.addWidget(self.info, 4, 1, 1, 3)
layout.addWidget(self.button, 5, 1, 1, 3)

QGridLayout把界面分成网格,并把某个视图对象附着在特定的网格位置。比如说,addWidget()(self.info, 4, 1, 1, 3)表示把一个文本框对象放在第4排、第1列的位置。该文本框纵向将占据1排,横向占据3列。这样,上下层视图的位置关系就通过布局确定了下来。除了网格式的布局,PyQT还支持其他形式的布局,如横向堆砌、纵向堆砌等等,可以进一步了解。

除了QWidget,PyQT还提供了常用的对话框,如:

self.path = QtGui.QFileDialog.getOpenFileName(self, self.button.text())

这里的QFileDialog对话框用于选择文件。对话框将访问所选文件的路径。除了文件选择,对话框还有确认对话框、文件输入对话框、色彩对话框。这些对话框实现了不少常用的GUI输入功能。通过利用这些对话框,可以减少程序员从头开发的工作量。

多线程

GUI界面的主线程通常留给应用做主循环。其他的很多工作要通过其他的线程来完成。PyQT多线程编程很简单,只需要重写QThread的run()方法就可以了:

class PollTimeThread(QtCore.QThread):def __init__(self, parent):super(PollTimeThread, self).__init__(parent)def run(self):...

创建线程后,只需要调用start()方法,就可以运行:

self.thread = PollTimeThread()
...
self.thread.start()       # 启动线程
...
self.thread.terminate()   # 终止线程

信号与槽

GUI经常要用到异步处理。比如说点击某个按钮,然后调用相应的回调函数。QT的“信号与槽”(signal-slot)机制就是为了解决异步处理问题。我们在线程中创建了信号,并通过emit()方法来发出信号:

class PollTimeThread(QtCore.QThread):"""This thread works as a timer."""update = QtCore.pyqtSignal()def __init__(self, parent):super(PollTimeThread, self).__init__(parent)def run(self):while True:time.sleep(1)if self.isRunning():# emit signalself.update.emit()else:return

有了信号,我们就可以给该信号连接到一个“槽”,其实就是对应于该信号的回调函数:

self.thread.update.connect(self.update)

每当信号被发出时,“槽”就会被调用。在这个例子中,就是更新视频播放时间。QT中的“信号与槽”是普遍存在的机制。一些组建如按键,预设了“点击”这样的信号,可以直接对应到“槽”。如代码中的:

self.button.clicked.connect(self.handleButton)

此外,Phonon是一个很好用的多媒体模块,使用方法也很简单,可以参考代码本身,这里不再赘述。

Python使用PyQT制作视频播放器相关推荐

  1. pythonweb视频播放器_干货分享,Python与PyQT制作视频播放器

    最近研究了Python的两个GUI包,Tkinter和PyQT.这两个GUI包的底层分别是Tcl/Tk和QT.相比之下,我觉得PyQT使用起来更加方便,功能也相对丰富.这一篇用PyQT实现一个视频播放 ...

  2. python制作视频播放器_Python使用PyQT制作视频播放器!专属播放器~

    原标题:Python使用PyQT制作视频播放器!专属播放器~ 最近研究了Python的两个GUI包,Tkinter和PyQT.这两个GUI包的底层分别是Tcl/Tk和QT.相比之下,我觉得PyQT使用 ...

  3. python制作视频播放器_Python应用03 使用PyQT制作视频播放器

    最近研究了Python的两个GUI包,Tkinter和PyQT.这两个GUI包的底层分别是Tcl/Tk和QT.相比之下,我觉得PyQT使用起来更加方便,功能也相对丰富.这一篇用PyQT实现一个视频播放 ...

  4. python开发视频播放器_Python应用03 使用PyQT制作视频播放器实例

    最近研究了Python的两个GUI包,Tkinter和PyQT.这两个GUI包的底层分别是Tcl/Tk和QT.相比之下,我觉得PyQT使用起来更加方便,功能也相对丰富.这一篇用PyQT实现一个视频播放 ...

  5. Python应用03 使用PyQT制作视频播放器

    最近研究了Python的两个GUI包,Tkinter和PyQT.这两个GUI包的底层分别是Tcl/Tk和QT.相比之下,我觉得PyQT使用起来更加方便,功能也相对丰富.这一篇用PyQT实现一个视频播放 ...

  6. python制作视频播放器_Python编程使用PyQT制作视频播放器

    最近研究了Python的两个GUI包,Tkinter和PyQT.这两个GUI包的底层分别是Tcl/Tk和QT.相比之下,我觉得PyQT使用起来更加方便,功能也相对丰富.这一篇用PyQT实现一个视频播放 ...

  7. python开发视频播放器_Python使用PyQT制作视频播放器

    最近研究了Python的两个GUI包,Tkinter和PyQT.这两个GUI包的底层分别是Tcl/Tk和QT.相比之下,我觉得PyQT使用起来更加方便,功能也相对丰富.这一篇用PyQT实现一个视频播放 ...

  8. OpenCV C++案例实战二十一《制作视频播放器》

    OpenCV C++案例实战二十一<制作视频播放器> 前言 一.源码 二.效果 总结 前言 本文将使用OpenCV C++ 制作简易视频播放器,用于实现视频播放基本功能. 1.通过创建滑动 ...

  9. 用了都说好的Python专属无广告视频播放器,良心到想为它疯狂打call

    导语​ 各位新老朋友下午好,我是木木子!掌声在哪里~ 咳咳咳.....算了没掌声我也还是要继续叨叨! 大家电脑上应该都有视频播放器吧,为了看电视电影下载了等各种影音. 还记得上学那会,寝室的同学都用的 ...

最新文章

  1. (转)利用ArcScene进行三维地形模拟
  2. SQL2005客户端连接到SQL2000服务器存在的问题
  3. canvas 闭合_想使用SVG或者canvas 手绘闭合多边形,使用vml效果已经实现了,由于vml只能支持ie所以想转成SVG或canvas...
  4. codeforces570C
  5. 在使用flask下载文件时会出现的一个文件下载不到的问题
  6. 在控制台显示sql语句,类似hibernate show_sql.
  7. OpenGL ES SDK for Android - 4
  8. jquery name选择器_Jquery--1
  9. 基于神经网络的实体识别和关系抽取联合学习
  10. html新建盒子,html+css 盒子模式展示(备查)
  11. MRTK 当进入某个物体时调用的函数
  12. Entity Framework 延伸系列目录
  13. 入门Sysmac Studio,白菜妹子是这样做的。
  14. 开发微信小程序需要服务器吗?
  15. MIR7 金额计算公式
  16. Java自动生成编号
  17. 和风天气更新数据失败原因分析
  18. 鸿蒙os手机有哪些,华为正式发布鸿蒙手机操作系统 鸿蒙操作系统是什么?鸿蒙适用机型首曝光...
  19. 字节跳动 Java 岗一二三面全经过分享
  20. EMC Navisphere AGENT(NAVIAGENT) 安装日志

热门文章

  1. javascript-分支与循环
  2. usermod使用方法
  3. NFS与NAS谁更适合VMware
  4. Quartus II 与ModelSim-SE联合仿真Shift_ram
  5. 【LeetCode】12. Integer to Roman 整型数转罗马数
  6. linux:shell:tree
  7. android播放html5视频,仅仅有声音没有图像视频
  8. Jquery attr 和removeAttr 的简单使用
  9. 从渲染页面的角度来聊一聊浏览器的工作原理
  10. NodeJS中使用SQLite3