<p>不能将无限while循环与GUI的循环一起使用。只要有IO操作要完成,就应该使用线程</p>
<p>示例代码:</p>
<pre class="lang-py prettyprint-override"><code>import cv2
import threading
import tkinter as tk
from PIL import Image, ImageTk
from queue import Queue
def stop_rec():
global running, after_id
running = False
if after_id:
root.after_cancel(after_id)
after_id = None
with frame_queue.mutex:
frame_queue.queue.clear()
def start_capture():
global capture
capture = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
video_writer = cv2.VideoWriter(r"sample.avi", fourcc, 30.0, (640, 480))
while running:
rect, frame = capture.read()
if rect:
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
videoImg = Image.fromarray(cv2image)
# current_frame = ImageTk.PhotoImage(image = videoImg)
frame_queue.put(videoImg)
video_writer.write(frame)
capture.release()
video_writer.release()
def update_frame():
global after_id
if not frame_queue.empty():
video_label.image_frame = ImageTk.PhotoImage(frame_queue.get_nowait())
video_label.config(image=video_label.image_frame)
after_id = root.after(10, update_frame)
def start_rec():
global running
stop_rec()
running = True
thread = threading.Thread(target=start_capture, daemon=True)
thread.start()
update_frame()
def closeWindow():
stop_rec()
root.destroy()
running = False
after_id = None
frame_queue = Queue()
root = tk.Tk()
root.protocol("WM_DELETE_WINDOW", closeWindow)
video_label = tk.Label()
video_label.pack(expand=True, fill="both")
tk.Button(text="Start", command=start_rec).pack()
tk.Button(text="stop", command=stop_rec).pack()
root.mainloop()
</code></pre>
<p>快速解释:</p>
<ul>
<li>在新线程中启动record函数</李>
<li>使用队列存储帧</李>
<li>然后使用<code>[widget].after</code>定期更新标签</李>
<li>要停止录制,请使用<code>[widget].after_cancel(after_id)</code>(在使用<code>.after</code>方法时返回_id之后),并将正在运行的变量设置为<code>False</code>以停止循环</李>
</ul>