我有一个Tkinter gui,用复选框打开一个单独的gui。在这个单独的窗口中,我需要引用复选框的状态,但是我收到以下错误:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1470, in __call__
return self.func(*args)
File "C:\@ Batch\LMS Python Script\tester3.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()
答案 0 :(得分:1)
你试图用global
拉扯的这个小黑客是我以前从未见过的东西 - 感谢原创性:-),但我不建议你继续沿着这条道路前进,因为要让它发挥作用是一件非常大的痛苦(如果它甚至可能),并且在长期维护中会更加痛苦。
永远不要害怕。 是更好的方式!通常在这种情况下,我建议使用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个复选框变量)。有关更深入的解释,请参阅Keep data out of your variable names,Ned Batchelder的优秀文章。
精明的读者可能会注意到将整个应用程序转换为类可以获得好处(您可以在__init__
中设置初始UI)。我肯定会推荐这种方法,但我没有写出来让这个建议尽可能简单。
答案 1 :(得分:0)
我能够获得原始代码。我不得不在错误的位置进行全局声明......我还必须首先在主循环中定义变量。我知道有更优雅的方法可以做到这一点,但它确实有效。
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)