python - 如何为视频播放器选择文件
问题描述
我是类和 PyQt5 的新手,并尝试使用 PyQt5 和 Opencv 构建视频播放器。使用OpenCV Video Capture with PyQt4中的代码并进行更改以将 PyQt4 中的命令转换为 PyQt5 并添加暂停按钮,我现在有了一个带有暂停、播放、结束和退出按钮的视频播放器。这是运行良好的代码:
import cv2
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QPushButton,
QVBoxLayout, QFileDialog
fileName = 'C:/Users/Art/Downloads/testVideo.mp4'
class Capture():
def __init__(self):
self.capturing = False
self.c = cv2.VideoCapture(fileName)
def startCapture(self):
self.capturing = True
cap = self.c
while(self.capturing):
ret, frame = cap.read()
cv2.imshow("Capture", frame)
cv2.waitKey(5)
cv2.destroyAllWindows()
def endCapture(self):
self.capturing = False
def pauseCapture(self):
if cv2.waitKey(0) & 0xFF == ord('p'): # Pause
self.capturing = False
def quitCapture(self):
cap = self.c
cv2.destroyAllWindows()
cap.release()
QtCore.QCoreApplication.quit()
class Window(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.setWindowTitle('Control Panel')
self.capture = Capture()
self.start_button = QPushButton('Start', self)
self.start_button.clicked.connect(self.capture.startCapture)
self.end_button = QPushButton('End', self)
self.end_button.clicked.connect(self.capture.endCapture)
self.pause_button = QPushButton('Pause', self)
self.pause_button.clicked.connect(self.capture.pauseCapture)
self.quit_button = QPushButton('Quit', self)
self.quit_button.clicked.connect(self.capture.quitCapture)
vbox = QVBoxLayout(self)
vbox.addWidget(self.start_button)
vbox.addWidget(self.end_button)
vbox.addWidget(self.pause_button)
vbox.addWidget(self.quit_button)
self.setLayout(vbox)
self.setGeometry(100, 100, 200, 200)
self.show()
if __name__== '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())
到目前为止,我将视频文件名及其路径硬编码到代码 (fileName) 中。现在,我想添加一个加载按钮,让用户选择视频。像这样的东西:
self.load_button = QPushButton('Load', self)
self.load_button.clicked.connect(self.pick_video)
def pick_video():
dialog = QtGui.QFileDialog()
fileName = dialog.getExistingDirectory(None,
"Select Folder")
return fileName
并将加载按钮添加到现有按钮列表中,如下所示:
vbox.addWidget(self.load_button)
我的问题是我不知道如何将其合并到现有代码中。如果我把它放在 Window 类中,它会给我一个错误。我的问题是如何将这样的内容添加到现有代码中,以便用户可以在按下加载按钮后选择视频文件。
编辑:根据@ekhumoro 更改代码后,我得到了这样的结果:
import cv2
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QPushButton,
QVBoxLayout, QFileDialog
class Capture():
def __init__(self):
self.capturing = False
def startCapture(self, path):
self.capturing = True
self.c = cv2.VideoCapture(path)
while self.capturing:
ret, frame = self.c.read()
cv2.imshow("Capture", frame)
cv2.waitKey(5)
cv2.destroyAllWindows()
def endCapture(self):
self.capturing = False
def pauseCapture(self):
if cv2.waitKey(0) & 0xFF == ord('p'): # Pause
self.capturing = False
def quitCapture(self):
cap = self.c
cv2.destroyAllWindows()
cap.release()
QtCore.QCoreApplication.quit()
class Window(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.setWindowTitle('Control Panel')
self.capture = Capture()
self.start_button = QPushButton('Start', self)
self.start_button.clicked.connect(self.start)
self.end_button = QPushButton('End', self)
self.end_button.clicked.connect(self.capture.endCapture)
self.pause_button = QPushButton('Pause', self)
self.pause_button.clicked.connect(self.capture.pauseCapture)
self.quit_button = QPushButton('Quit', self)
self.quit_button.clicked.connect(self.capture.quitCapture)
vbox = QVBoxLayout(self)
vbox.addWidget(self.start_button)
vbox.addWidget(self.end_button)
vbox.addWidget(self.pause_button)
vbox.addWidget(self.quit_button)
self.setLayout(vbox)
self.setGeometry(100, 100, 200, 200)
self.show()
def start(self):
path = QtWidgets.QFileDialog.getOpenFileName(self)[0]
if path:
self.capture.startCapture(path)
if __name__== '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())
但是,当我运行此代码时,出现此错误:AttributeError: 'Window' object has no attribute 'start'。另一件事是我想为这个过程有一个单独的按钮,这意味着一旦用户运行代码,在打开的窗口中,他/她可以点击那个按钮(我们称之为加载按钮),然后选择视频文件,我在这段代码中没有看到。我在某处遗漏了什么吗?或者,重新排列的代码可能不是@ekhumoro 的意思。
解决方案
重新排列代码以startCapture
获取path
参数。然后在开始按钮的插槽中的文件对话框中传递路径:
class Capture():
def __init__(self):
self.capturing = False
def startCapture(self, path):
self.capturing = True
self.c = cv2.VideoCapture(path)
while self.capturing:
ret, frame = self.c.read()
cv2.imshow("Capture", frame)
cv2.waitKey(5)
cv2.destroyAllWindows()
class Window(QtWidgets.QWidget):
def __init__(self):
...
self.start_button = QPushButton('Start', self)
self.start_button.clicked.connect(self.start)
...
def start(self):
path = QtWidgets.QFileDialog.getOpenFileName(self)[0]
if path:
self.capture.startCapture(path)
这是一个完整的替代实现:
import cv2
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QPushButton,QVBoxLayout, QFileDialog
class Capture():
def __init__(self):
self.capturing = False
self.c = None
def setVideoFile(self, path):
if self.c is not None:
cv2.destroyAllWindows()
self.c.release()
self.c = cv2.VideoCapture(path)
self.startCapture()
def startCapture(self):
self.capturing = True
cap = self.c
while(self.capturing):
ret, frame = cap.read()
cv2.imshow("Capture", frame)
cv2.waitKey(5)
cv2.destroyAllWindows()
def endCapture(self):
self.capturing = False
def pauseCapture(self):
if cv2.waitKey(0) & 0xFF == ord('p'): # Pause
self.capturing = False
def quitCapture(self):
cap = self.c
cv2.destroyAllWindows()
cap.release()
QtCore.QCoreApplication.quit()
class Window(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.setWindowTitle('Control Panel')
self.capture = Capture()
self.open_button = QPushButton('Open', self)
self.open_button.clicked.connect(self.open)
self.start_button = QPushButton('Start', self)
self.start_button.clicked.connect(self.capture.startCapture)
self.end_button = QPushButton('End', self)
self.end_button.clicked.connect(self.capture.endCapture)
self.pause_button = QPushButton('Pause', self)
self.pause_button.clicked.connect(self.capture.pauseCapture)
self.quit_button = QPushButton('Quit', self)
self.quit_button.clicked.connect(self.capture.quitCapture)
vbox = QVBoxLayout(self)
vbox.addWidget(self.open_button)
vbox.addWidget(self.start_button)
vbox.addWidget(self.end_button)
vbox.addWidget(self.pause_button)
vbox.addWidget(self.quit_button)
self.setLayout(vbox)
self.setGeometry(100, 100, 200, 200)
self.show()
def open(self):
path = QtWidgets.QFileDialog.getOpenFileName(self)[0]
if path:
self.capture.setVideoFile(path)
if __name__== '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())
推荐阅读
- javascript - 开玩笑返回 Firebase 函数的误报?
- sqlbulkcopy - Microsoft.Data.SqlClient.SqlBulkCopy 的两个构造函数之间有什么区别吗?
- druid - Apache Druid - 在多值维度中保留元素的顺序
- gremlin - 对 JanusGraph 的 Gremling 控制台查询随机缓慢
- javascript - Javascript 事件处理和调用堆栈问题/内存泄漏
- python - 使用 Python 在终端中运行聊天室时出现无限循环错误
- git - 我不确定从哪里重新设置我的功能分支?
- javascript - 直接访问子文件夹中的 Angular 9 路由会抛出 404?
- c# - uwp 组合框 ContainerfromIndex(0) 始终返回 null
- java - 如何在 Thymeleaf 的文本中创建链接?