在简单的GUI代码中获取Tkinter回调错误

时间:2017-05-16 13:50:59

标签: python-2.7 tkinter state-machine

所以我试图为一个我在树莓派上做的小项目制作这个GUI。基本上,状态机根据按钮按下来改变状态(想象它就像一个小测验)。出于某种原因,当我运行模块时,我收到一条错误消息:

Exception in Tkinter callback
Traceback (most recent call last): 
File:"/usr/lib/python2.7/lib-tk/Tkinter.py", line 1535, in __call__
     return self.func(*args)
File:"/usr/lib/python2.7/lib-tk/Tkinter.py", line 586, in callit
     func(*args)
File "/home/pi/Desktop/SafetyDoorknob.py", line 79, in safety_loop
NameError: global name 'currentState' is not defined

我已根据此错误代码在互联网上搜索了很多内容,但我找不到任何有帮助的内容。我是Python和Tkinter的新手(在上周内)我想知道这里是否有人可以提供帮助。以下是我的代码的副本。提前感谢您的帮助,请耐心等待,因为我还在学习这类东西

import Tkinter as tk
from PIL import Image, ImageTk
import requests
import time
import RPi.GPIO as GPIO
import random
import os
import sys

Button_A = 29 # The GPIO pin the button is attached to
Button_B = 31 # The GPIO pin the button is attached to
Button_C = 33 # The GPIO pin the button is attached to
Button_D = 35 # The GPIO pin the button is attached to
Button_Confirm = 37 # The GPIO pin the button is attached to

Relay_Contact = 38

#//////Setting up the pinmodes///////
GPIO.setmode(GPIO.BCM) #Defines what the numbering scheme is for the pins
GPIO.setup(Button_A, GPIO.IN, pull_up_down=GPIO.PUD_UP) #Setting the button as an input and turning on some Pull-up resistors
GPIO.setup(Button_B, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(Button_C, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(Button_D, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(Button_Confirm, GPIO.IN,pull_up_down=GPIO.PUD_UP)

GPIO.setup(Relay_Contact, GPIO.OUT) #Making the Relay contact an output.

global usableQuestions
global currentState
global stateStartTime
global picPath
global correctAnswer
global allAnswers

mainFolderPath = "/home/pi/SafetyDoorknob/AllQuestions" #All Level Folders will be in SafetyDoorknob
answersPath = "/home/pi/SafetyDoorknob/DoorknobAnswers.txt"
picPath = "/home/pi/SafetyDoorknob/HomeScreen.jpg"
answers_file = open(answersPath,'r')
allAnswers = answers_file.readline().split(",") #Load all answers into String Array
usableQuestions = os.listdir(mainFolderPath)


root = tk.Tk()
root.geometry("800x480")
root.configure(background = 'black')
root.wm_attributes('-type','splash')

def buttonPressToAnswer():
    currentAnswer = ""

    if GPIO.input(Button_A) == 0:
        time.sleep(0.02)
        currentAnswer = "A"
    elif GPIO.input(Button_B) == 0:
        time.sleep(0.02)
        currentAnswer = "B"
    elif GPIO.input(Button_C) == 0:
        time.sleep(0.02)
        currentAnswer = "C"
    elif GPIO.input(Button_D) == 0:
        time.sleep(0.02)
        currentAnswer = "D"

    return currentAnswer


def get_State_Time():

    stateTime = time.time() - stateStartTime
    return int(round(stateTime))

def setState(newState):
    currentState = newState
    stateStartTime = time.time()

def safety_loop():

    if currentState == 0: #Startup State
        picPath = "/home/pi/SafetyDoorknob/HomeScreen.jpg"

        if GPIO.input(Button_Confirm) == 0:
            time.sleep(0.02)
            while GPIO.input(Button_Confirm) == 0:
                pass
            setState(1)
            picPath = pick_rand_img()
        root.after(10,safety_loop)

    elif currentState == 1: #Question 1 State
        while get_State_Time() <= 120:
            if buttonPressToAnswer() == correctAnswer:
                break
            else:
                pass
        if get_State_Time() <=120:
            setState(2)
            picPath = pick_rand_img()
        else:
            setState(0)

        root.after(10,safety_loop)

    elif currentState == 2: #Question 2 State
        while get_State_Time() <= 120:
            if buttonPressToAnswer() == correctAnswer:
                break
            else:
                pass
        if get_State_Time() <=120:
            setState(3)
            picPath = pick_rand_img()
        else:
            setState(0)

        root.after(10,safety_loop)

    elif currentState == 3: #Question 3 State
        while get_State_Time() <= 120:
            if buttonPressToAnswer() == correctAnswer:
                break
            else:
                pass
        if get_State_Time() <=120:
            setState(4)
            picPath = pick_rand_img()
        else:
            setState(0)

        root.after(10,safety_loop)

    elif currentState == 4: #Door Open State

        GPIO.output(Relay_Contact,1)
        time.sleep(60)
        GPIO.output(Relay_Contact,0)


def pick_rand_img():

    if len(usableQuestions) == 0:

        usableQuestions = os.listdir(mainFolderPath)


    randomIndex = random.randint(0,len(usableQuestions) - 1)
    randQuestion = usableQuestions[randomIndex] #Picks random question
    correctAnswer = allAnswers[randomIndex]


    newQuestionPath = mainFolderPath + randQuestion
    usableQuestions.pop(randomIndex)
    allAnswers.pop(randomIndex)

    return newQuestionPath

img = ImageTk.PhotoImage(Image.open(picPath))
panel = tk.Label(root,image = img)

panel.pack(side = "bottom",fill = "both",expand = "yes")
setState(0)
root.after(10,safety_loop)
root.mainloop()

1 个答案:

答案 0 :(得分:1)

您应该currentState setState函数中的def setState(newState): currentState = newState 为全局变量。

setState

setState中创建了一个局部变量,其他函数无法使用。你的def setState(newState): ## make currentStage and stateStartTime global global currentState, stateStartTime currentState = newState stateStartTime = time.time() 功能应该是:

global

您还应该使用上面显示的awk关键字 - 更改全局变量的其他函数(我无法完全测试您的代码,因为我没有一些模块)