界面开发(4)--- PyQt5实现打开图像及视频播放功能

PyQt5创建打开图像及播放视频页面

上篇文章主要介绍了如何实现登录界面的账号密码注册及登录功能,还简单介绍了有关数据库的连接方法。这篇文章我们介绍一下如何在设计的页面中打开本地的图像,以及实现视频播放功能。

实现打开图像功能

为了便于记录实现细节,我们尽量一步步地来。之前的文章已经介绍过如何将新的页面与之前的页面建立连接了,这里就不再赘述,从建立新页面开始。

  1. 首先将label拖到屏幕中央,并在左侧设计成合适的宽和高,用于显示图像和视频。

在这里插入图片描述

  1. 这个label是透明的,为了方便展示,我们为它填充个黑色,呈现出一种幕布的感觉。
  • 使用鼠标右击 label 中心,点击改变样式表;
  • 点击添加颜色,background-color;
  • 选择黑色,点击ok;
  • 然后再点击Apply,最后点击ok。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  1. 之后,在下面拖入 Push Button 按钮和 Text Browser 按钮,分别用于打开本文文件,以及显示打开的路径。

在这里插入图片描述

做到这里基础界面就算完成了,将其保存,并使用PyUIC工具转化为.py文件,剩下的部分就剩编写逻辑代码了。

在显示图像方面,我们主要的思想就是通过点击“打开文件”按钮,来选取本地库中的图像,并把路径显示到文本框中。self.image的取值用来判断选取的不是图像的情况。核心代码如下:

class Image_open(QMainWindow, image.Ui_MainWindow):
    def __init__(self, parent=None):
        super(Image_open, self).__init__(parent)
        # UI界面
        self.setupUi(self)
        self.pushButton.clicked.connect(self.open_image)
        
	def open_image(self):
		self.image = None
		# 获取图像的路径
        self.img_path = QFileDialog.getOpenFileName()[0]
        # 将路径存储到对话框中
        self.textBrowser.setText(self.img_path)
        # 可选的图像格式
        img_type = [".bmp", ".jpg", ".png", ".gif"]
        for ig in img_type:
            if ig not in self.img_path:
                continue
            else:
            	self.image = True
            	# 如果是图像文件名的话,读取图像
                img = QPixmap(self.img_path)
                # 获取图像的宽和高
                w = img.width()
                h = img.height()
                # 根据图像与label的比例,最大化图像在label中的显示
                ratio = max(w / self.label.width(), h / self.label.height())
                img.setDevicePixelRatio(ratio)
                # 图像在label中居中显示
                self.label.setAlignment(Qt.AlignCenter)
                self.label.setPixmap(img)
        if self.image is None:
            QMessageBox.information(self, "警告", "我们暂时不支持此格式的文件!", QMessageBox.Ok)

上面单独介绍了打开图像的代码,是为了方便阅读和理解。

而视频播放和打开图像的部分代码是可以共同使用的,因此下面的视频播放也会将打开图像的代码进行介绍。

实现视频播放功能

为了实现视频播放,暂停和关闭功能,我们额外增加了两个 Push Button 按钮,其中左边的那个按钮要实现本地视频的播放与暂停,右边的按钮用于实现视频的关闭。

在这里插入图片描述

接下来是逻辑代码部分。

可以发现我们的两个按钮上面并没有写汉字,这是为了我们在逻辑代码中给他加入标准图标。第一个按钮是播放的图标,第二个按钮是关闭的图标。

为了方便展示,我们把这些连接的设置都放在一个函数里。

 def background(self):
 		# 文件选择按钮
        self.pushButton.clicked.connect(self.open_image)
        # 视频播放图标
        self.pushButton_2.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))  # 播放图标
        self.pushButton_3.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))  # 停止图标
        
        # 用于开始播放视频的按钮
        self.pushButton_2.clicked.connect(self.play_file) # 这是对应的函数
        # 用于关闭播放视频的按钮
        self.pushButton_3.clicked.connect(self.close_file) # 这是对应的函数
        
		# 当播放的为图像时,设计这两个按钮不能点击,只有当播放的是视频时,才能点击
        self.pushButton_2.setEnabled(False)
        self.pushButton_3.setEnabled(False

重复上面的判断文件类型函数,这里我们考虑了视频及图像。

当所选文件为视频时,将播放按钮置为可使用。

def pre_judge(self):
   # 创建文件对话框,如果是视频,令self.video = True,如果是图像,令self.video = False,
   # 当self.video = None时,报错。
    self.video = None
    self.img_path = QFileDialog.getOpenFileName()[0]
    self.textBrowser.setText(self.img_path)
    video_type = [".mp4", ".mkv", ".MOV", "avi"]
    img_type = [".bmp", ".jpg", ".png", ".gif"]
    for vdi in video_type:
        if vdi not in self.img_path:
            continue
        else:
            self.video = True
            # 当是视频时,将开始按钮置为可点击状态
            self.pushButton_2.setEnabled(True)
    for ig in img_type:
        if ig not in self.img_path:
            continue
        else:
            self.video = False
            img = QPixmap(self.img_path)
            w = img.width()
            h = img.height()
            ratio = max(w / self.label.width(), h / self.label.height())
            img.setDevicePixelRatio(ratio)
            self.label.setAlignment(Qt.AlignCenter)
            self.label.setPixmap(img)
    if self.video is None:
        QMessageBox.information(self, "警告", "我们暂时不支持此格式的文件!", QMessageBox.Ok)

这里介绍如何播放视频,这里是整个的重点,也是难点。

播放视频,主要是使用其中的 QTimer 计时器,如果计时器被激活,就每隔一段时间读取一个视频帧,并显示。

我们根据计时器是否激活,是否被阻塞,将开始播放按钮置为暂停或播放,主要由 self.playing 参数控制。

self.timer.isActive() 用来判断是否有视频流,用于开始播放视频

self.timer.blockSignals(True) 用于暂停视频流。

self.timer.blockSignals(False) 用于重新播放视频流。

import sys
from PyQt5.QtWidgets import QMessageBox, QFileDialog, QLineEdit
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import mainwindow, image
import cv2
import sqlite3

### 主页面设计,略
class MainWindow(QMainWindow, mainwindow.Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.image_open = Image_open()
        self.pushButton.clicked.connect(self.image_open.show)
### 未详细说明,请参考前三篇博客
        
class Image_open(QMainWindow, image.Ui_MainWindow):
    def __init__(self, parent=None):
        super(Image_open, self).__init__(parent)
        # UI界面
        self.setupUi(self)
        self.background()
        self.cap = cv2.VideoCapture()
        self.num = 1
        self.playing = False
        # 在label中播放视频
        self.init_timer()
        
	def background(self):
 		# 文件选择按钮
        self.pushButton.clicked.connect(self.pre_judge)
        # 视频播放图标
        self.pushButton_2.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))  # 播放图标
        self.pushButton_3.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))  # 停止图标
        
        # 用于开始播放视频的按钮
        self.pushButton_2.clicked.connect(self.play_file) # 这是对应的函数
        # 用于关闭播放视频的按钮
        self.pushButton_3.clicked.connect(self.close_file) # 这是对应的函数
        
		# 当播放的为图像时,设计这两个按钮不能点击,只有当播放的是视频时,才能点击
        self.pushButton_2.setEnabled(False)
        self.pushButton_3.setEnabled(False)
        
    def pre_judge(self):
	   	# 创建文件对话框,如果是视频,令self.video = True,如果是图像,令self.video = False,
	  	# 当self.video = None时,报错。
	    self.video = None
	    self.img_path = QFileDialog.getOpenFileName()[0]
	    self.textBrowser.setText(self.img_path)
	    video_type = [".mp4", ".mkv", ".MOV", "avi"]
	    img_type = [".bmp", ".jpg", ".png", ".gif"]
	    for vdi in video_type:
	        if vdi not in self.img_path:
	            continue
	        else:
	            self.video = True
	            # 当是视频时,将开始按钮置为可点击状态
	            self.pushButton_2.setEnabled(True)
	    for ig in img_type:
	        if ig not in self.img_path:
	            continue
	        else:
	            self.video = False
	            img = QPixmap(self.img_path)
	            w = img.width()
	            h = img.height()
	            ratio = max(w / self.label.width(), h / self.label.height())
	            img.setDevicePixelRatio(ratio)
	            self.label.setAlignment(Qt.AlignCenter)
	            self.label.setPixmap(img)
	    if self.video is None:
	        QMessageBox.information(self, "警告", "我们暂时不支持此格式的文件!", QMessageBox.Ok)
	        
 	# 打开本地视频文件
    def play_file(self):
        self.label.setEnabled(True)
        # 如果播放视频,则使得关闭视频按钮可用
        self.pushButton_3.setEnabled(True)
        # 视频流阻塞信号关闭
        self.timer.blockSignals(False)
        # 如果计时器没激活,证明是暂停阶段,需要重新播放,并把self.playing = True。
        if self.timer.isActive() is False:
            self.cap.open(self.img_path)
            self.timer.start(30)
            self.playing = True
            # 更换播放按钮为暂停按钮
            self.set_state()
        # 如果计时器激活了,并且num为奇数,证明是播放阶段,需要暂停播放,并把self.playing = False。
        elif self.timer.isActive() is True and self.num % 2 == 1:
            self.timer.blockSignals(True)
            self.playing = False
            self.num = self.num + 1
            self.set_state()
        # 如果计时器激活了,并且num为偶数,证明经过播放阶段,现在是暂停阶段,需要重新开始播放,并把self.playing = True。
        elif self.timer.isActive() is True and self.num % 2 == 0:
            self.num = self.num + 1
            self.timer.blockSignals(False)
            self.playing = True
            self.set_state()
        else:
            QMessageBox.information(self, "警告", "视频播放错误!", QMessageBox.Ok)

    # 关闭本地视频
    def close_file(self):
        self.cap.release()
        self.pushButton_2.setEnabled(True)
        self.pushButton_3.setEnabled(False)
        self.timer.stop()
        self.playing = False
        # 关闭视频将按钮置为可以播放
        self.set_state()

    # 本地视频播放暂停转换图标按钮
    def set_state(self):
        if self.playing:
        	# 暂停图标
            self.pushButton_2.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))

        else:
            self.pushButton_2.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
  
    # 播放视频画面
    def init_timer(self):
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.show_pic)

    # 显示视频图像
    def show_pic(self):
        ret, img = self.cap.read()
        if ret:
            cur_frame = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            # 视频流的长和宽
            height, width = cur_frame.shape[:2]
            pixmap = QImage(cur_frame, width, height, QImage.Format_RGB888)
            pixmap = QPixmap.fromImage(pixmap)
            # 获取是视频流和label窗口的长宽比值的最大值,适应label窗口播放,不然显示不全
            ratio = max(width/self.label.width(), height/self.label.height())
            pixmap.setDevicePixelRatio(ratio)
            # 视频流置于label中间部分播放
            self.label.setAlignment(Qt.AlignCenter)
            self.label.setPixmap(pixmap)

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

完成出来的结果大概就是这样的!

在这里插入图片描述

该专栏博文地址:

界面开发(1) — PyQt5环境配置
界面开发(2)— 使用PyQt5制作用户登陆界面
界面开发(3)— PyQt5用户登录界面连接数据库
界面开发(4)— PyQt5实现打开图像及视频播放功能
界面开发(5)— PyQt5实现打开摄像头采集视频功能

奥比中光深度相机(一) — 环境配置
奥比中光深度相机(二) — PyQt5实现打开深度摄像头功能

日常学习记录,一起交流讨论吧!侵权联系~

  • 33
    点赞
  • 243
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 22
    评论
可以使用PyQt中的QMediaPlayer和QVideoWidget来播放视频,然后使用QPixmap来截取QVideoWidget中的当前帧作为截图。以下是一个简单的示例代码: ```python from PyQt5.QtCore import Qt, QUrl from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QVBoxLayout, QHBoxLayout, QFileDialog, QSizePolicy, QSlider, QStyle, QSizePolicy, QSpacerItem, QVideoWidget from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer from PyQt5.QtGui import QPixmap class VideoPlayer(QWidget): def __init__(self): super().__init__() self.setWindowTitle("Video Player") # 创建播放器和视频窗口 self.media_player = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.video_widget = QVideoWidget() self.media_player.setVideoOutput(self.video_widget) # 创建截图按钮 self.screenshot_button = QPushButton("Screenshot", self) self.screenshot_button.clicked.connect(self.take_screenshot) # 创建标签来显示截图 self.screenshot_label = QLabel() self.screenshot_label.setAlignment(Qt.AlignCenter) self.screenshot_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.screenshot_label.setMinimumSize(240, 135) # 创建布局 video_layout = QVBoxLayout() video_layout.addWidget(self.video_widget) button_layout = QHBoxLayout() button_layout.addStretch(1) button_layout.addWidget(self.screenshot_button) button_layout.addStretch(1) screenshot_layout = QVBoxLayout() screenshot_layout.addWidget(QLabel("Screenshot:")) screenshot_layout.addWidget(self.screenshot_label) main_layout = QVBoxLayout() main_layout.addLayout(video_layout) main_layout.addLayout(button_layout) main_layout.addLayout(screenshot_layout) self.setLayout(main_layout) # 打开视频文件 file_path, _ = QFileDialog.getOpenFileName(self, "Open Video File", "", "Video Files (*.mp4 *.avi *.mkv)") if file_path: self.media_player.setMedia(QMediaContent(QUrl.fromLocalFile(file_path))) self.media_player.play() def take_screenshot(self): # 截取当前帧 pixmap = self.video_widget.grab() self.screenshot_label.setPixmap(pixmap) if __name__ == '__main__': app = QApplication([]) player = VideoPlayer() player.show() app.exec_() ``` 这个程序会打开一个视频文件,可以播放视频,并且有一个截图按钮,点击该按钮可以截取视频当前帧并在界面上显示。
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WYKB_Mr_Q

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值