简体   繁体   中英

nameerror: global name is not defined in tkinter

# -*- coding: utf-8 -*-
from Tkinter import *
import Image, ImageTk
import test2

root = Tk()
root.wm_title("InterActMap")

def get():


    global CountryName
    CountryName = e1.get()
    global Day
    Day = e2.get()
    global Month
    Month = e3.get()
    global Year
    Year = e4.get()
    Monthint=int(Month)
    Dayint=int(Day)
    Yearint=int(Year)

    if CountryName == "germany" and Monthint == 8 and Dayint == 26 and Yearint == 1914:
    global a
        a = Button(root, bg = "red", text ="Battle of Tannenberg" , command=None)
        a.place(x=691, y=229)
        test2.register(a, Tannenberg)

left a few if's out here for brevitys sake but its the same thing with a few different battles, naming buttons a,b,c,d,e,f,etc.

def forget():
    a.place_forget()
    b.place_forget()
    c.place_forget()
    d.place_forget()
    f.place_forget()


canvas = Canvas(root, width = 1280, height=720)

country = Label(root, text = "Country")
country.place(x=5, y=5)
e1 = Entry(root)
e1.place(x=60,y=5)

day = Label(root, text = "Day")
day.place(x=230, y=5)
e2 = Entry(root)
e2.place(x=260, y=5)

month = Label(root, text = "Month")
month.place(x=430, y=5)
e3 = Entry(root)
e3.place(x=475, y=5)

year = Label(root, text = "Year")
year.place(x=645, y=5)
e4 = Entry(root)
e4.place(x=680, y=5)



File = "map1.jpg"
img = ImageTk.PhotoImage(Image.open(File))
canvas.create_image(0,0,image=img,anchor="nw")

Button1 = Button(root, text = "Submit", command=get)
Button1.place(x=850, y=5)
Button2 = Button(root, text = "Clear", command=forget)
Button2.place(x=925, y=5)
Button3 = Button(root, text = "Exit", command=root.quit)
Button3.place(x=960, y=5)




canvas.pack()
root.mainloop()

I know the problem is that when I click clear all of the buttons dont necessarily exist so it throws an error...

NameError: global name 'c' is not defined

And then any buttons in forget() after the one that is not defined are not going to be cleared.

After looking around at similar questions I saw that defining the variable as something so that even if all the if statements arent true and all buttons are not created the variable at least has a value. That didnt work and I would just get

AttributeError: 'NoneType' object has no attribute 'forget'

I figured out a workaround, but its not really what I want

if CountryName == "germany" and Monthint == 8 and Dayint == 26 and Yearint == 1914:
    global a
        a = Button(root, bg = "red", text ="Battle of Tannenberg" , command=forget)
        a.place(x=691, y=229)
        test2.register(a, Tannenberg)

With this when I have multiple buttons/battles on the map, if I just click any one of them it clears the map. The same error is thrown but at least the map is cleared. I've tried to make this work but I'm pulling my hair out, appreciate any help!

The best thing to do would be to create an instance-level list that contains all your buttons. For instance:

button_list = []

if CountryName == "germany" and Monthint == 8 and Dayint == 26 and Yearint == 1914:
    a = Button(root, bg = "red", text ="Battle of Tannenberg" , command=None)
    a.place(x=691, y=229)
    button_list.append(a)

Then your forget command should be something like:

def forget(lst_to_clear):
    for button in reversed(lst_to_clear):
        button.place_forget()
        lst_to_clear.pop()
        # the reversal is to make sure popping the item out of the
        # original list doesn't break the for loop. You could just
        # as easily do:
        # # while lst_to_clear:
        # #     lst_to_clear.pop().place_forget()
        # but I find it a little less readable.

and your clear BUTTON should look like:

Button2 = Button(root, text = "Clear", command=lambda: forget(button_list))
Button2.place(x=925, y=5)

So you could use the try/except handler in this case. Small example:

from tkinter import *

root = Tk()

def forget()
    for x in (a, b, c, d, e, f, g):
        try:
            x.place_forget()
        except NameError:
            pass

a = Button(text = 'hi', command = forget)
a.place(x = 0, y = 0)

root.mainloop()

here the code will return a NameError because b , c , d etc. don't exist.The exception then deals with this, so you aren't interrupted.

hope that helps you!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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