定义子函数中的python全局变量



我有一个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)

相关内容

  • 没有找到相关文章

最新更新