2017-03-17 64 views
0

我有一個Tkinter GUI,其中三個按鈕分別運行一個單獨的腳本。其中兩個加載正常,但第三個拋出一個NameError,說我的名字之一沒有定義。但是,當我不通過GUI運行腳本時,它運行良好。Tkinter按鈕執行腳本拋出NameError

這是GUI代碼:

import sys 
import os 
import tkinter 
import cv2 
from tkinter.filedialog import askopenfilename 
from tkinter import messagebox 
import numpy as np 
import matplotlib.pyplot as plt 

top=tkinter.Tk() 
top.geometry("300x350") 
top.config(background='black') 
top.title('Test') 
top.resizable(height=False, width=False) 

def thresholdCallBack(): 
    exec(open('motionindexthreshold.py').read()) 

def autoremoveCallBack(): 
    exec(open('motionindexgenerator.py').read()) 

def videoTaggingCallBack(): 
    exec(open('stepthrough.py').read()) 

def quitCallBack(): 
    top.destroy() 

M = tkinter.Message(top, text='Test', width=280, background='black', foreground='white', font=('Courier', 28)) 
B = tkinter.Button(top,text="Define Motion Index Threshold",command= thresholdCallBack) 
C = tkinter.Button(top,text="Autoremove Nonmovement Video Segments",command= autoremoveCallBack) 
D = tkinter.Button(top,text="Tag Video Frames",command= videoTaggingCallBack) 
E = tkinter.Button(top,text="Quit", command=quitCallBack) 
B.config(height=5, width=80, background='red') 
C.config(height=5, width=80, background='blue', foreground='white') 
D.config(height=5, width=80, background='yellow') 
E.config(height=5, width=80, background='green') 
M.pack() 
B.pack() 
C.pack() 
D.pack() 
E.pack() 
top.mainloop() 

這是當一個按鍵被註冊了崩潰python腳本:

import cv2 
import tkinter as tk 
from tkinter.filedialog import askopenfilename 
from tkinter import messagebox 
import numpy as np 
import os 
import matplotlib.pyplot as plt 
import sys 


framevalues = [] 
count = 1 

root = tk.Tk() 
root.withdraw() 

selectedvideo = askopenfilename() 
selectedvideostring = str(selectedvideo) 
cap = cv2.VideoCapture(selectedvideo) 
length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) 


def stanceTag():  
    framevalues.append('0' + ' ' + '|' + ' ' + str(int(cap.get(1)))) 
    print (str(int(cap.get(1))), '/', length) 
    print(framevalues) 

def swingTag(): 
    framevalues.append('1' + ' ' + '|' + ' ' + str(int(cap.get(1)))) 
    print (str(int(cap.get(1))), '/', length) 
    print(framevalues) 

def unsureTag(): 
    framevalues.append('-1' + ' ' + '|' + ' ' + str(int(cap.get(1)))) 
    print (str(int(cap.get(1))), '/', length) 
    print(framevalues) 

def rewindFrames(): 
    cap.set(1,((int(cap.get(1)) - 2))) 
    print (int(cap.get(1)), '/', length) 
    framevalues.pop() 
    print(framevalues) 



while (cap.isOpened()): 
    ret, frame = cap.read() 

    # check if read frame was successful 
    if ret == False: 
      break 
    # show frame first 
    cv2.imshow('frame',frame) 

    # then waitKey 
    frameclick = cv2.waitKey(0) & 0xFF 

    if frameclick == ord('a'): 
     swingTag() 

    elif frameclick == ord('r'): 
     rewindFrames() 

    elif frameclick == ord('s'): 
     stanceTag() 

    elif frameclick == ord('d'): 
     unsureTag() 

    elif frameclick == ord('q'): 
     with open((selectedvideostring + '.txt'), 'w') as textfile: 
      for item in framevalues: 
       textfile.write("{}\n".format(item)) 
     break 

    else: 
     continue 

cap.release() 
cv2.destroyAllWindows() 

沒有人有任何想法如何解決這個問題呢?

感謝

+0

某些內容正在由您的GUI腳本導入,而不是由下標導入。 NameError會告訴你什麼名字丟失。修復方法是使用正確的導入來執行腳本而不是exec。 – Novel

回答

2

如果你需要從另一個python腳本運行的代碼,那麼你應該使用導入來獲取其他腳本並運行其他腳本的功能。這會對代碼造成問題,因爲你的程序核心不在函數中,所以一旦它被導入就會運行。由於(和其他)的原因,你應該把所有的代碼放在函數中。您可以通過檢查__main__屬性來檢測代碼是否已導入。

我重構了代碼以將所有代碼移入函數,然後導入它並從GUI按鈕調用適當的函數。

這是你的GUI代碼應該是什麼樣子:

import tkinter 

import motionindexthreshold 
import motionindexgenerator 
import stepthrough 

def main(): 
    top=tkinter.Tk() 
    top.geometry("300x350") 
    top.config(background='black') 
    top.title('Test') 
    top.resizable(height=False, width=False) 

    M = tkinter.Message(top, text='Test', width=280, background='black', foreground='white', font=('Courier', 28)) 
    B = tkinter.Button(top,text="Define Motion Index Threshold",command=motionindexthreshold.main) 
    C = tkinter.Button(top,text="Autoremove Nonmovement Video Segments",command=motionindexgenerator.main) 
    D = tkinter.Button(top,text="Tag Video Frames",command=stepthrough.main) 
    E = tkinter.Button(top,text="Quit", command=top.destroy) 
    B.config(height=5, width=80, background='red') 
    C.config(height=5, width=80, background='blue', foreground='white') 
    D.config(height=5, width=80, background='yellow') 
    E.config(height=5, width=80, background='green') 
    M.pack() 
    B.pack() 
    C.pack() 
    D.pack() 
    E.pack() 
    top.mainloop() 

if __name__ == '__main__': 
    main() 

這是你的模塊代碼應該是什麼樣子:

import cv2 
import tkinter as tk 
from tkinter.filedialog import askopenfilename 

def stanceTag(cap, framevalues):  
    framevalues.append('0' + ' ' + '|' + ' ' + str(int(cap.get(1)))) 
    print (str(int(cap.get(1))), '/', length) 
    print(framevalues) 

def swingTag(cap, framevalues): 
    framevalues.append('1' + ' ' + '|' + ' ' + str(int(cap.get(1)))) 
    print (str(int(cap.get(1))), '/', length) 
    print(framevalues) 

def unsureTag(cap, framevalues): 
    framevalues.append('-1' + ' ' + '|' + ' ' + str(int(cap.get(1)))) 
    print (str(int(cap.get(1))), '/', length) 
    print(framevalues) 

def rewindFrames(cap, framevalues): 
    cap.set(1,((int(cap.get(1)) - 2))) 
    print (int(cap.get(1)), '/', length) 
    framevalues.pop() 
    print(framevalues) 


def main(): 
    framevalues = [] 
    count = 1 

    selectedvideo = askopenfilename() 
    selectedvideostring = str(selectedvideo) 
    cap = cv2.VideoCapture(selectedvideo) 
    length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) 

    while (cap.isOpened()): 
     ret, frame = cap.read() 

     # check if read frame was successful 
     if ret == False: 
       break 
     # show frame first 
     cv2.imshow('frame',frame) 

     # then waitKey 
     frameclick = cv2.waitKey(0) & 0xFF 

     if frameclick == ord('a'): 
      swingTag(cap, framevalues) 

     elif frameclick == ord('r'): 
      rewindFrames(cap, framevalues) 

     elif frameclick == ord('s'): 
      stanceTag(cap, framevalues) 

     elif frameclick == ord('d'): 
      unsureTag(cap, framevalues) 

     elif frameclick == ord('q'): 
      with open((selectedvideostring + '.txt'), 'w') as textfile: 
       for item in framevalues: 
        textfile.write("{}\n".format(item)) 
      break 

     else: 
      continue 

    cap.release() 
    cv2.destroyAllWindows() 

if __name__ == '__main__': 
    # this is called if this code was not imported ... ie it was directly run 
    # if this is called, that means there is no GUI already running, so we need to create a root 
    root = tk.Tk() 
    root.withdraw() 
    main() 

顯然,這是一種猜測;我無法測試這是否解決了您的問題,但我認爲它會。

+1

如果你能描述你改變了什麼,這個答案會更好。否則,OP必須逐行比較您的解決方案與原始解決方案。 –

+0

非常感謝,這真的很有幫助,並解決了我的大部分問題 - 只有一個問題,當我按任意鍵運行我的一個函數時,出現'framevalues'未定義的名稱錯誤。我怎樣才能解決這個問題?乾杯 – KittenMittons

+0

我忽略了你在你的功能中也需要這個。只要通過像'帽'一樣。我已經更新了我的答案以證明這一點。 – Novel