【问题标题】:Video player by Python tkinter, When I pause video, I cannot re-playPython tkinter的视频播放器,当我暂停视频时,我无法重新播放
【发布时间】: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)
  • 您能否给我更多提示我应该在代码中的哪个位置使用它?

标签: python video tkinter pause


【解决方案1】:

我将为播放按钮回调创建另一种方法。像这样的:

def play_start(self):
    self.pause = False
    self.play_video()

但是,如果播放按钮已经在播放,我会确保您禁用它。否则,如果多次按下播放按钮,您可能会有多个 play_video 的“实例”。


另一种方法是将播放和暂停按钮组合在一起,以便切换self.pause 的值。这样你就可以只有一个按钮和一个回调函数了。

【讨论】:

    【解决方案2】:

    问题:暂停按钮将不起作用。

    参考


    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
        

        【讨论】:

        • 请对您的代码进行一些解释
        猜你喜欢
        • 1970-01-01
        • 2019-02-03
        • 1970-01-01
        • 2019-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-16
        • 2018-05-28
        相关资源
        最近更新 更多