Python tkinter的视频播放器,当我暂停视频时,我无法重新播放
Posted
技术标签:
【中文标题】Python tkinter的视频播放器,当我暂停视频时,我无法重新播放【英文标题】:Video player by Python tkinter, When I pause video, I cannot re-play 【发布时间】:2019-06-25 15:31:33 【问题描述】:我正在创建 GUI 来播放视频文件。问题是当我暂停视频时,播放按钮无法重新播放该视频,我必须再次选择视频文件。
注意:由于我想在同一个 tkinter 窗口中显示视频,所以我不使用 OpenCV imshow 命令。相反,我使用的是“window.after”方法。
以下是我的代码:
我尝试使用“self.pause”变量来控制暂停状态。当我单击暂停按钮时,此布尔变量变为 True。但是,当我再次单击“播放”按钮时,我找不到合适的位置使其变为 False。
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
import PIL.Image, PIL.ImageTk
import cv2
class videoGUI:
def __init__(self, window, window_title):
self.window = window
self.window.title(window_title)
top_frame = Frame(self.window)
top_frame.pack(side=TOP, pady=5)
bottom_frame = Frame(self.window)
bottom_frame.pack(side=BOTTOM, pady=5)
self.pause = False # Parameter that controls pause button
self.canvas = Canvas(top_frame)
self.canvas.pack()
# Select Button
self.btn_select=Button(bottom_frame, text="Select video file", width=15, command=self.open_file)
self.btn_select.grid(row=0, column=0)
# Play Button
self.btn_play=Button(bottom_frame, text="Play", width=15, command=self.play_video)
self.btn_play.grid(row=0, column=1)
# Pause Button
self.btn_pause=Button(bottom_frame, text="Pause", width=15, command=self.pause_video)
self.btn_pause.grid(row=0, column=2)
self.delay = 15 # ms
self.window.mainloop()
def open_file(self):
self.pause = False
self.filename = filedialog.askopenfilename(title="Select file", filetypes=(("MP4 files", "*.mp4"),
("WMV files", "*.wmv"), ("AVI files", "*.avi")))
print(self.filename)
# Open the video file
self.cap = cv2.VideoCapture(self.filename)
self.width = self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)
self.height = self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
self.canvas.config(width = self.width, height = self.height)
def get_frame(self): # get only one frame
try:
if self.cap.isOpened():
ret, frame = self.cap.read()
return (ret, cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
except:
messagebox.showerror(title='Video file not found', message='Please select a video file.')
def play_video(self):
# Get a frame from the video source, and go to the next frame automatically
ret, frame = self.get_frame()
if ret:
self.photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(frame))
self.canvas.create_image(0, 0, image = self.photo, anchor = NW)
if not self.pause:
self.window.after(self.delay, self.play_video)
def pause_video(self):
self.pause = True
# Release the video source when the object is destroyed
def __del__(self):
if self.cap.isOpened():
self.cap.release()
##### End Class #####
# Create a window and pass it to videoGUI Class
videoGUI(Tk(), "EnJapan")
如果我在“play_video”函数中编写以下代码:
self.pause = False
暂停按钮不起作用。因为“window.after”方法会自动调用“play_video”函数并使“self.pause”为False。因此,暂停按钮将不起作用。
【问题讨论】:
使用self.after_id = self.window.after(...
和self.after_cancel(self.after_id)
您能否给我更多提示我应该在代码中的哪个位置使用它?
【参考方案1】:
我将为播放按钮回调创建另一种方法。像这样的:
def play_start(self):
self.pause = False
self.play_video()
但是,如果播放按钮已经在播放,我会确保您禁用它。否则,如果多次按下播放按钮,您可能会有多个 play_video
的“实例”。
另一种方法是将播放和暂停按钮组合在一起,以便切换self.pause
的值。这样你就可以只有一个按钮和一个回调函数了。
【讨论】:
【参考方案2】:问题:暂停按钮将不起作用。
参考:
Tkinter.Widget.after-method - after(delay_ms, callback=None, *args)
注册一个在给定时间后调用的回调。
Tkinter.Widget.after_cancel-method - after_cancel(id)
取消回调。
到cancel
已经为events
排队的self.play_video
更改以下内容:
def play_video(self):
...
if self.pause:
self.window.after_cancel(self.after_id)
else:
self.after_id = self.window.after(self.delay, self.play_video)
【讨论】:
@stovfi 'self.after_id' 代表什么? @Ekin “self.after_id
代表什么?”:我已经用参考链接更新了我的答案。 after_id
是从 .after(...
返回的标识符。【参考方案3】:
只需在 play_video(self) 方法中添加:
if self.pause == True:
self.pause = False
return
【讨论】:
【参考方案4】:from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
import PIL.Image, PIL.ImageTk
import cv2
class videoGUI:
def __init__(self, window, window_title):
self.window = window
self.window.title(window_title)
top_frame = Frame(self.window)
top_frame.pack(side=TOP, pady=5)
bottom_frame = Frame(self.window)
bottom_frame.pack(side=BOTTOM, pady=5)
self.pause = False # Parameter that controls pause button
self.canvas = Canvas(top_frame)
self.canvas.pack()
# Select Button
self.btn_select=Button(bottom_frame, text="Select video file", width=15, command=self.open_file)
self.btn_select.grid(row=0, column=0)
# Play Button
self.btn_play=Button(bottom_frame, text="Play", width=15, command=self.play_video)
self.btn_play.grid(row=0, column=1)
# Pause Button
self.btn_pause=Button(bottom_frame, text="Pause", width=15, command=self.pause_video)
self.btn_pause.grid(row=0, column=2)
# Resume Button
self.btn_resume=Button(bottom_frame, text="resume", width=15, command=self.resume_video)
self.btn_resume.grid(row=0, column=3)
self.delay = 15 # ms
self.window.mainloop()
def open_file(self):
self.pause = False
self.filename = filedialog.askopenfilename(title="Select file", filetypes=(("MP4 files", "*.mp4"),
("WMV files", "*.wmv"), ("AVI files", "*.avi")))
print(self.filename)
# Open the video file
self.cap = cv2.VideoCapture(self.filename)
self.width = self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)
self.height = self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
self.canvas.config(width = self.width, height = self.height)
def get_frame(self): # get only one frame
try:
if self.cap.isOpened():
ret, frame = self.cap.read()
return (ret, cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
except:
messagebox.showerror(title='Video file not found', message='Please select a video file.')
def play_video(self):
# Get a frame from the video source, and go to the next frame automatically
ret, frame = self.get_frame()
if ret:
self.photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(frame))
self.canvas.create_image(0, 0, image = self.photo, anchor = NW)
if not self.pause:
self.window.after(self.delay, self.play_video)
def pause_video(self):
self.pause = True
#Addition
def resume_video(self):
self.pause=False
self.play_video()
# Release the video source when the object is destroyed
def __del__(self):
if self.cap.isOpened():
self.cap.release()
##### End Class #####
# Create a window and pass it to videoGUI Class
videoGUI(Tk(), "EnJapan")
【讨论】:
【参考方案5】:if not self.pause:
self.window.after(self.delay, self.play_video)
else:
self.pause = False
【讨论】:
请对您的代码进行一些解释以上是关于Python tkinter的视频播放器,当我暂停视频时,我无法重新播放的主要内容,如果未能解决你的问题,请参考以下文章
如何在 python TKinter 中使用 GStreamer 在视频播放器中调整大小和裁剪?
单击视频时,如何使用 Javascript 切换多个视频的播放/暂停?
使用带有 pylab/matplotlib 嵌入的 Tkinter 播放、暂停、停止功能的彩色绘图动画:无法更新图形/画布?