在函数

时间:2017-12-13 07:36:46

标签: python python-3.x tkinter

我正在使用一个允许用户从列表中选择项目并将索引存储到变量中的函数。我想在函数外部使用该变量,但它不起作用。

这是我到目前为止所拥有的。 (仅供参考:未显示mylist部分代码)

class FirstWindow(Frame):
    selection_index = '0'
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)

         num_lines_lights = 4
         scrollbar = Scrollbar(self)
         #scrollbar.pack(side=RIGHT, fill=Y)
         scrollbar.place(x=55,y=200)
         #scrollbar.place(x=25, y=50)
         mylist = Listbox(self, yscrollcommand = scrollbar.set)
         for line in range(num_lines_lights):
             mylist.insert(END, "Light " + str(line))
         mylist.pack(side = LEFT, fill = BOTH)
         mylist.place(x=70,y=200)
         scrollbar.config(command = mylist.yview)

        def select_item(event):
            global selection_index
            widget = event.widget
            selection_index = (widget.curselection()[0])
            value = widget.get(index)
            print("Inside function %s " % selection_index) #works fine

        mylist.bind('<<ListboxSelect>>', select_item)

        print("This is return %s " % selection_index) #NOT WORKING

这是我收到的错误:

print("This is return %s " % selection_index)
NameError: name 'selection_index' is not defined

2 个答案:

答案 0 :(得分:0)

因为global关键字,它限制了变量的范围。您可以使用self并在def __init__()

中定义变量,而不是全局
def __init__(self, parent, controller):
    self.selection_index = '0'

现在,而不是使用selection_index使用self.selection_index

答案 1 :(得分:0)

您不应该尝试使用global。使用类的一个主要原因是它可以以一种易于访问的方式保存相关对象。

您可以使selection_index成为FirstWindow的实例属性。像这样:

class FirstWindow(Frame):
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        self.selection_index = '0'

        def select_item(event):
            widget = event.widget
            selection_index = (widget.curselection()[0])
            value = widget.get(index)
            print("Inside function %s " % self.selection_index)

        mylist.bind('<<ListboxSelect>>', select_item)

        print("This is return %s " % self.selection_index)

当然,这只会打印This is return 0,因为select_item还没有机会运行。

这是一个基于你发布的新代码的可运行示例,它仍然不是MCVE:我必须添加额外的东西才能让它可以运行。顺便说一下,你不应该在一个容器小部件中混合使用不同的布局方法(包,地点,网格),因为它们不会相互合作。

我已添加了一个额外的按钮,以证明self.selection_indexFirstWindow可用{。}}。

from tkinter import *

class FirstWindow(Frame):
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        self.selection_index = '-1'

        num_lines_lights = 4
        scrollbar = Scrollbar(self)
        scrollbar.pack(side=RIGHT, fill=Y)
        mylist = Listbox(self, yscrollcommand=scrollbar.set)
        for line in range(num_lines_lights):
            mylist.insert(END, "Light " + str(line))
        mylist.pack(side=LEFT, fill=BOTH)
        scrollbar.config(command = mylist.yview)

        def select_item(event):
            widget = event.widget
            self.selection_index = (widget.curselection()[0])
            value = widget.get(self.selection_index)
            print("Inside function %s: %s" % (self.selection_index, value))

        mylist.bind('<<ListboxSelect>>', select_item)
        print("This is return %s " % self.selection_index)

        # A button to print the current selection_index
        Button(parent, text='Show index', command=self.show_index).pack()

    def show_index(self):
        print(self.selection_index)

root = Tk()
win = FirstWindow(root, root)
win.pack()
root.mainloop()

顺便说一句,使用from tkinter import *会更好。相反,使用

import tkinter as tk

然后你会做root = tk.Tk()scrollbar = tk.Scrollbar(self)之类的东西。这使得代码更容易阅读,因为它清楚地表明了导入名称的来源,并阻止了Tkinter的转储超过130个名称到您的全局命名空间,这可能导致名称冲突。