在tkinter多处理脚本中的mainloop之前退出函数调用

时间:2013-06-15 10:35:51

标签: python events opencv tkinter

下方的脚本会打开视频文件会将其显示在tkinter标签中。帧采集是在另一个过程中完成的。

我的问题是我的quit_()函数在加载视频(python解释器然后空闲)后调用它时会成功关闭完整脚本,但会破坏根窗口并离开程序运行如果我在加载视频之前尝试退出(python解释器然后挂起,我必须手动杀死它)。 loadswitch变量是 tkinter BooleanVar ,用于检测视频的加载,并使脚本在进入主循环之前等待其值更改。

在我看来,问题是没有文件路径作为参数的事实导致image_capture()中的某种异常导致退出问题。但是,脚本执行没有异常。

如果想在视频加载之前如何让完整脚本在quit_()上终止,我们将不胜感激!

我的剧本:

#!/usr/bin/python

import numpy as np
from multiprocessing import Process, Queue, Pipe
from Queue import Empty
import cv2
import cv2.cv as cv
from PIL import Image, ImageTk
import time
import Tkinter as tk
import tkMessageBox
import tkFileDialog

#tkinter GUI functions----------------------------------------------------------
def quit_(root, process):
   if tkMessageBox.askokcancel(message='Are you sure you want to quit?', icon='question', title='Quit'):
      process.terminate()
      root.destroy()

def load_win(root, loadswitch, con):
   #create child window when 'load video' button is clicked
   win = tk.Toplevel()
   win.resizable(False, False)
   #displays message, radiobuttons to choose data type, and gets the absolute file path if file
   tk.Label(win, text='Please choose video data type:').grid(column=0, row=0)
   videotype = tk.StringVar()
   videostream = tk.Radiobutton(win, text='Video live stream', variable=videotype, value='videostream').grid(column=0, row=1)
   videofile = tk.Radiobutton(win, text='Video file', variable=videotype, value='videofile').grid(column=0, row=2)
   def load_video(root, win, videotype):
      if videotype.get()=='videostream':
         win.destroy()
         #loadswitch.set(True)   #line to activate when stream capture code implemented
      elif videotype.get()=='videofile':
         filepath = tkFileDialog.askopenfilename()
         win.destroy()
         if filepath:
            loadswitch.set(True)
            con.send(filepath)
         else:
            pass
   tk.Button(win, text='OK', command=lambda: load_video(root, win, videotype)).grid(column=0, row=3)
   root.wait_window(win)

def update_image(image_label, queue, waitframe,root,process):
   if queue.get()==None:
      quit_(root,process)
   else:
      frame = queue.get()
      im = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
      a = Image.fromarray(im)
      b = ImageTk.PhotoImage(image=a)
      image_label.configure(image=b)
      image_label._image_cache = b  # avoid garbage collection
      root.update()
      time.sleep(waitframe)

def update_all(root, image_label, queue,waitframe,process):
   update_image(image_label, queue, waitframe,root,process)
   root.after(0, func=lambda: update_all(root, image_label, queue,waitframe,process))

#multiprocessing image processing functions-------------------------------------
def image_capture(queue,con):
   videopath = con.recv()
   vidFile = cv2.VideoCapture(videopath)#pour mettre la web cam, changer pour 0 et commenter les ligne passant fps et waitframe
   fps = vidFile.get(cv2.cv.CV_CAP_PROP_FPS)
   waitframe = 1/fps
   con.send(waitframe)#sending waitkey duration through pipe to update_image()
   while True:
      try:
         flag, frame=vidFile.read()
         if flag==0:
            queue.put(None)
            break
         else:
            #image processing code goes here
            queue.put(frame)
            cv2.waitKey(10)
      except:
         continue

if __name__ == '__main__':
#initialize multiprocessing
queue = Queue()
pcon, ccon = Pipe()
#start video procesing
p = Process(target=image_capture, args=(queue,ccon))
p.start()
#GUI of root window (les menus arretent la video, car ils occupent le processus...)
root = tk.Tk()
root.protocol("WM_DELETE_WINDOW", root.iconify)
root.title('FlowMap 0.1')
root.resizable(False, False)
image_label = tk.Label(master=root)# label for the video frame
image_label.grid(column=0, row=0, columnspan=2, rowspan=1)
#fill label with image until video is loaded
bg_im = ImageTk.PhotoImage(file='logo.png')
image_label['image'] = bg_im
# quit button
quit_button = tk.Button(master=root, text='Quit',command=lambda: quit_(root,p))
quit_button.grid(column=1, row=1)
#load video button and a switch to wait for the videopath to be chosen
loadswitch = tk.BooleanVar(master=root, value=False, name='loadswitch')
load_button = tk.Button(master=root, text='Load video',command=lambda: load_win(root, loadswitch, pcon))
load_button.grid(column=0, row=1)
#print an 'about' window
tkMessageBox.showinfo(message="FlowMap 0.1, (c) Raoul SCHORER 2013")
#wait for input to begin processing
root.wait_variable(loadswitch)
waitframe = pcon.recv()
print 'waitframe is: '+ str(waitframe)
# setup the update callback
root.after(0, func=lambda: update_all(root, image_label, queue, waitframe,p))
#exit program
root.mainloop()
print 'mainloop exit'
p.terminate()
print 'image capture process exit'

0 个答案:

没有答案