Tkinter和绑定到ListboxSelect事件的两个列表框的意外行为

发布于 2021-01-29 17:57:28

我正在处理的脚本中遇到一个异常问题。该程序是用Python3 /
Tkinter编写的。它初始化两个列表框,包装在两个单独的框架中,并根据用户的命令显示一个或另一个。当用户在第一个列表框中选择一个项目,然后决定更改屏幕并在第二个框架中选择一个项目时,就会出现异常。

我创建了一个示例代码(如下),以复制该问题。使用此代码,在运行时,单击第一个列表框(白色背景)中的一个项目将使第二个列表框出现(橙色背景)。同样,第一个对象是“未包装的”,因此用户将不再能够与其进行交互。最后,单击第二个列表框中的项目,会从第一个对象的“
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()
关注者
0
被浏览
215
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    默认情况下,tkinter一次只允许一个窗口小部件保留选择。因此,当您在第二个列表框中选择某项时,将取消选择在第一个列表框中选择的项目。这将导致您的函数被调用。发生这种情况时,self.lb1.curselection()[0])由于选择为空,将引发错误。

    一个简单的解决方案是,当您在第二个列表框中选择某些内容时,使选择在第一个列表框中保持不变,这是将两个列表框的exportselection选项False都设置为。

    self.lb1 = tk.Listbox(self, exportselection=False)
    ...
    self.lb2 = tk.Listbox(self, bg='orange', exportselection=False)
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看