将视频播放器与进度条关联起来,需要使用Scale组件的command参数来调用更新视频帧的函数。
首先,在VideoPlayer类的__init__方法中,将进度条的command参数设置为self.update_frame。
self.progressbar = tk.Scale(self.root, from_=0, to=self.total_frames, orient=tk.HORIZONTAL, length=500, command=self.update_frame)
然后,在VideoPlayer类中定义update_frame方法,用于更新视频帧和进度条的值。
def update.current_frame = int(self.progressbar.get())
self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.current_frame)
ret, frame = self.cap.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image = Image.fromarray(frame)
photo = ImageTk.PhotoImage(image=image)
self.canvas.create_image(0, 0, anchor=tk.NW, image=photo)
self.canvas.image = photo
这样,每次拖动进度条时,就会调用update_frame方法更新视频帧。
完整的代码示例:
import tkinter as tk
from tkinter import filedialog
import cv2
from PIL import Image, ImageTk
class VideoPlayer:
def __init__(self, video_path):
self.video_path = video_path
self.cap = cv2.VideoCapture(video_path)
self.total_frames = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
self.root = tk.Tk()
self.root.title("Video Player")
self.root.geometry('1080x720')
self.root['bg'] = '#333333'
self.root.iconbitmap('stop.JPG')
movieImage = Image.open('dy.JPG')
cover = ImageTk.PhotoImage(image=movieImage)
self.canvas = tk.Canvas(self.root, width=1080, height=720, bd=0, image=cover)
self.root.iconbitmap('stop.JPG')
self.canvas.pack()
self.progressbar = tk.Scale(self.root, from_=0, to=self.total_frames, orient=tk.HORIZONTAL, length=500, command=self.update_frame)
self.progressbar.pack()
self.volume_slider = tk.Scale(self.root, from_=0, to=100, orient=tk.HORIZONTAL, length=200, cursor='hand2', command=self.update_volume)
self.volume_slider.pack()
self.play_button = tk.Button(self.root, text="Play", cursor='hand2', command=self.play_video)
self.play_button.pack()
self.pause_button = tk.Button(self.root, text="Pause", cursor='hand2', command=self.pause_video)
self.pause_button.pack()
self.current_frame = 0
self.volume = 50
self.update_frame()
self.update_volume()
self.root.mainloop()
def update_frame(self, event=None):
self.current_frame = int(self.progressbar.get())
self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.current_frame)
ret, frame = self.cap.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image = Image.fromarray(frame)
photo = ImageTk.PhotoImage(image=image)
self.canvas.create_image(0, 0, anchor=tk.NW, image=photo)
self.canvas.image = photo
def update_volume(self, event=None):
self.volume = self.volume_slider.get()
self.cap.set(cv2.CAP_PROP_VOLUME, self.volume / 100)
def play_video(self):
self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.current_frame)
while True:
ret, frame = self.cap.read()
if not ret:
break
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image = Image.fromarray(frame)
photo = ImageTk.PhotoImage(image=image)
self.canvas.create_image(0, 0, anchor=tk.NW, image=photo)
self.canvas.image = photo
self.current_frame += 1
self.progressbar.set(self.current_frame)
self.root.update()
def pause_video(self):
self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.current_frame)
ret, frame = self.cap.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image = Image.fromarray(frame)
photo = ImageTk.PhotoImage(image=image)
self.canvas.create_image(0, 0, anchor=tk.NW, image=photo)
self.canvas.image = photo
video_path = filedialog.askopenfilename(title="Select Video File",
filetypes=(("Video files", "*.mp4 *.avi"), ("All files", "*.*")))
if video_path:
player = VideoPlayer(video_path)
这样,就实现了通过拖动进度条来更新视频帧的功能。
上一篇
发表评论