【发布时间】:2020-06-13 00:59:19
【问题描述】:
我在正在编写的脚本中遇到了一个不寻常的问题。该程序是用 Python3/Tkinter 编写的。它初始化两个列表框,分别包裹在两个单独的框架中,并根据用户的命令显示一个或另一个。当用户在第一个 Listbox 中选择一个项目,然后决定切换屏幕并在第二个框架中选择一个项目时,会出现异常。
我创建了一个示例代码(如下)来复制问题。使用此代码,在运行时,单击第一个列表框(白色背景)中的一个项目会使第二个列表框出现(橙色背景)。此外,第一个对象是“解包”的,因此用户应该不再能够与其交互。最后,单击第二个 Listbox 中的项目,会在第一个对象的“on_select_1”方法中引发 IndexError。为什么该方法会在该事件之后执行?我很清楚自己作为程序员的局限性,但我很确定这不是应该发生的。
import tkinter as tk
class Listbox1(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.lb1 = tk.Listbox(self)
for i in ["item 1.1", "item 1.2", "item 1.3", "item 1.4"]:
self.lb1.insert(tk.END, i)
self.lb1.bind("<<ListboxSelect>>", self.on_select_1)
self.lb1.pack()
def on_select_1(self, *args):
try:
print("item {} selected in listbox 1".format(self.lb1.curselection()[0]))
except IndexError:
print("IndexError raised in method 'on_select_1'")
self.master.switch()
class Listbox2(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.lb2 = tk.Listbox(self, bg='orange')
for i in ["item 2.1", "item 2.2", "item 2.3", "item 2.4"]:
self.lb2.insert(tk.END, i)
self.lb2.bind("<<ListboxSelect>>", self.on_select_2)
self.lb2.pack()
def on_select_2(self, *args):
print("item {} selected in listbox 2".format(self.lb2.curselection()[0]))
class App(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.pack()
self.lb1_frame = Listbox1(self)
self.lb2_frame = Listbox2(self)
self.lb1_frame.pack()
def switch(self):
self.lb1_frame.pack_forget()
self.lb2_frame.pack()
def main():
root = tk.Tk()
app = App(root)
app.mainloop()
if __name__ == '__main__':
main()
【问题讨论】:
-
你做了什么来调试这个?索引越界错误是不言自明的。在尝试从中取出物品之前,您是否检查过
self.lbl.curselection()返回的内容?可能不是你想的那样。 -
嗨,Brian,尊敬的,我认为你没有抓住重点......超出范围的索引确实很容易捕捉,但不言自明的是为什么第二个 Listbox 对象会调用该方法在第一个列表框中。绑定正确完成,因此在第二个列表框中选择一个项目应该只运行它自己的“on_select_2”方法。它怎么会最终在另一个对象中调用“on_select_1”方法?
标签: python python-3.x tkinter listbox