将视频播放器与进度条关联起来,需要使用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)

这样,就实现了通过拖动进度条来更新视频帧的功能。

大家都在看: