简体   繁体   English

Tkinter按钮执行脚本抛出NameError

[英]Tkinter button executing script throws NameError

I have a Tkinter GUI with three buttons running a separate script each. 我有一个Tkinter GUI,其中三个按钮分别运行一个单独的脚本。 Two of them load fine, however the third one throws up a NameError, saying one of my names isn't defined. 其中两个可以很好地加载,但是第三个抛出了NameError,说我的名字之一没有定义。 However when I run the script not through the GUI, it runs fine. 但是,当我不通过GUI运行脚本时,它运行良好。

This is the GUI code: 这是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()

And this is the python script that crashes when a keypress is registered: 这是注册按键时崩溃的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()

Does anyone have any ideas how to solve this issue? 有谁知道如何解决这个问题?

Thanks 谢谢

If you need to run code from another python script, then you should use an import to get the other script and run a function in the other script. 如果您需要从另一个python脚本运行代码,则应该使用导入来获取另一个脚本并在另一个脚本中运行函数。 This will be a problem with your code since you have the core of your program outside of a function, so it would run as soon as it's imported. 这将是代码的问题,因为您将程序的核心置于函数之外,因此它将在导入后立即运行。 For the reason (and others) you should have all of your code in functions. 由于这个原因(以及其他原因),您应该在函数中包含所有代码。 You can detect if the code was imported or not by checking the __main__ attribute. 您可以通过检查__main__属性来检测代码是否已导入。

I restructured your code to move all the code into functions, then import it and call the appropriate function from the GUI buttons. 我对代码进行了重组,将所有代码移到函数中,然后将其导入并从GUI按钮调用适当的函数。

This is what your GUI code should look like: 这是您的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()

And this is what your module code should look like: 这是您的模块代码应如下所示:

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()

Obviously this is a guess; 显然这是一个猜测; I have no way to test if this solves your issue, but I think it will. 我无法测试这是否可以解决您的问题,但我认为可以。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM