繁体   English   中英

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

[英]Defining python global variable in sub function

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

您尝试使用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)

还要注意,每当您拥有一系列变量Foo1Foo2Foo3 ...时,通常都希望开始考虑使用其他数据结构(在这种情况下,您实际上可能希望使用复选框列表而不是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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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