我有一个Tkinter gui,它打开一个带有复选框的单独gui。在这个单独的窗口中,我需要引用复选框的状态,但是我得到了以下错误:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:Python27liblib-tkTkinter.py", line 1470, in __call__
return self.func(*args)
File "C:@ BatchLMS Python Scripttester3.pyw", line 23, in var_states
print("FX: %d, FY: %d, FZ: %d, MX: %d, MY: %d, MZ: %d" % (FX_1.get(), FY_1.get(), FZ_1.get(),MX_1.get(), MY_1.get(), MZ_1.get()))
NameError: global name 'FX_1' is not defined
是否可以从子函数定义和引用全局变量?
下面是我的代码:from Tkinter import *
import Tkinter
import tempfile
root = Tkinter.Tk()
root.title("Generate APDL")
root.geometry("200x225")
Lbl1 = Label(root, text="How many interface points?")
Lbl1.pack(side=TOP,padx=5,pady=5)
Entry1 = Entry(root, bd =1)
Entry1.pack(side=TOP,padx=5,pady=5)
def NewWindow():
IPoints=int(Entry1.get())
NumPoints=IPoints+1
master = Tkinter.Toplevel()
master.title("Select Unit Load Components")
def var_states():
print("FX: %d, FY: %d, FZ: %d, MX: %d, MY: %d, MZ: %d" % (FX_1.get(), FY_1.get(), FZ_1.get(),MX_1.get(), MY_1.get(), MZ_1.get()))
def CloseWindow():
master.destroy()
for i in xrange(1,NumPoints):
Label(master, text="PT_%d: " % i).grid(row=i,column=0, sticky=W)
exec('global FX_' + str(i)) in globals(), locals()
Checkbutton(master, text="FX", variable='FX_%d' % i).grid(row=i,column=2, sticky=W)
exec('global FY_' + str(i)) in globals(), locals()
Checkbutton(master, text="FY", variable='FY_%d' % i).grid(row=i,column=3, sticky=W)
exec('global FZ_' + str(i)) in globals(), locals()
Checkbutton(master, text="FZ", variable='FZ_%d' % i).grid(row=i,column=4, sticky=W)
exec('global MX_' + str(i)) in globals(), locals()
Checkbutton(master, text="MX", variable='MX_%d' % i).grid(row=i,column=5, sticky=W)
exec('global MY_' + str(i)) in globals(), locals()
Checkbutton(master, text="MY", variable='MY_%d' % i).grid(row=i,column=6, sticky=W)
exec('global MZ_' + str(i)) in globals(), locals()
Checkbutton(master, text="MZ", variable='MZ_%d' % i).grid(row=i,column=7, sticky=W)
Label(master, text=" ").grid(row=99,column=0, sticky=W)
Bttn1=Button(master, text='Generate APDL Snippet', command=var_states).grid(row=100,column=0, sticky=W)
Label(master, text=" ").grid(row=101,column=0, sticky=W)
Bttn2=Button(master, text='Close Window', command=CloseWindow)
Bttn2.grid(row=102,column=0, sticky=W)
Bttn1 = Tkinter.Button(root, text ="Open New Window", command = NewWindow)
Bttn1.pack(side = TOP,padx=10,pady=5)
root.mainloop()
你试图在global
中使用的这个小hack是我以前从未见过的——为你的独创性而喝彩:-),但我不建议你继续沿着这条路走下去,因为让它工作将是一个很大的痛苦(如果可能的话),并且在长期的维护中会更加痛苦。
不要害怕。有更好的方法!通常在这些情况下,我建议使用class
。有了一个类,你可以携带所有的状态,你需要随着self
。以下是代码的缩略版本:
class NewWindowFactory(object):
def var_states(self):
print 'FX_1', self.FX_1.get()
def NewWindow(self):
for i in xrange(1,NumPoints):
label = Label(master, text="PT_%d: " % i)
label.grid(row=i,column=0, sticky=W)
setattr(self, 'FX_' + str(i), label)
Button(master, text='Generate APDL Snippet', command=self.var_states).grid(row=100,column=0, sticky=W)
的用法是这样的:
factory = NewWindowFactory()
Bttn1 = Tkinter.Button(root, text="Open New Window", command = factory.NewWindow)
Bttn1.pack(side = TOP,padx=10,pady=5)
还请注意,每当您有一系列变量Foo1
, Foo2
, Foo3
…,您通常希望开始考虑使用不同的数据结构(在本例中,您实际上可能需要一个复选框列表,而不是10个复选框变量)。要了解更深入的解释,请参阅Ned Batchelder撰写的一篇优秀文章《让数据远离变量名》。
__init__
中设置初始UI),可以获得很多好处。我肯定会推荐这种方法,但我没有把它写出来,以使这个建议尽可能简单。
我能够让原始代码工作。我不得不在错误的地方进行全局声明……我还必须首先在主循环中定义变量。我知道有一种更优雅的方法可以做到这一点,但它确实有效。
for i in xrange(1,100):
exec('var1_' + str(i) + ' = Tkinter.IntVar()')
exec('var2_' + str(i) + ' = Tkinter.IntVar()')
exec('var3_' + str(i) + ' = Tkinter.IntVar()')
exec('var4_' + str(i) + ' = Tkinter.IntVar()')
exec('var5_' + str(i) + ' = Tkinter.IntVar()')
exec('var6_' + str(i) + ' = Tkinter.IntVar()')
def NewWindow():
IPoints=int(Entry1.get())
NumPoints=IPoints+1
MaxComp=IPoints*6
master = Tkinter.Toplevel()
master.title("Select Unit Load Components")
Label(master, text="Interface Points ").grid(row=0,column=0, sticky=W)
Label(master, text="FX").grid(row=0,column=1, sticky=W)
Label(master, text="FY").grid(row=0,column=2, sticky=W)
Label(master, text="FZ").grid(row=0,column=3, sticky=W)
Label(master, text="MX").grid(row=0,column=4, sticky=W)
Label(master, text="MY").grid(row=0,column=5, sticky=W)
Label(master, text="MZ").grid(row=0,column=6, sticky=W)
def var_states():
exec('global var1_' + str(i)) in globals(), locals()
exec('global var2_' + str(i)) in globals(), locals()
exec('global var3_' + str(i)) in globals(), locals()
exec('global var4_' + str(i)) in globals(), locals()
exec('global var5_' + str(i)) in globals(), locals()
exec('global var6_' + str(i)) in globals(), locals()
print("FX: %d, FY: %d, FZ: %d, MX: %d, MY: %d, MZ: %d" % (var1_15.get(), var2_15.get(), var3_15.get(),var4_15.get(), var5_15.get(), var6_15.get()))
for i in xrange(1,NumPoints):
Label(master, text="PT_%d: " % i).grid(row=i,column=0, sticky=W)
exec('Checkbutton(master, text=" ", variable=var1_' + str(i) + ').grid(row=i,column=1, sticky=W)') in globals(), locals()
exec('Checkbutton(master, text=" ", variable=var2_' + str(i) + ').grid(row=i,column=2, sticky=W)') in globals(), locals()
exec('Checkbutton(master, text=" ", variable=var3_' + str(i) + ').grid(row=i,column=3, sticky=W)') in globals(), locals()
exec('Checkbutton(master, text=" ", variable=var4_' + str(i) + ').grid(row=i,column=4, sticky=W)') in globals(), locals()
exec('Checkbutton(master, text=" ", variable=var5_' + str(i) + ').grid(row=i,column=5, sticky=W)') in globals(), locals()
exec('Checkbutton(master, text=" ", variable=var6_' + str(i) + ').grid(row=i,column=6, sticky=W)') in globals(), locals()
Button(master, text='Show', command=var_states).grid(row=100, sticky=W, pady=4)