python - Tkinter 和绑定(bind)到 ListboxSelect 事件的两个列表框出现意外行为

标签 python python-3.x tkinter listbox

我在正在处理的脚本中遇到了一个不寻常的问题。该程序是用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()

最佳答案

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

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

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

关于python - Tkinter 和绑定(bind)到 ListboxSelect 事件的两个列表框出现意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48991760/

相关文章:

python - .pip 配置了需要 TLS/SSL 的位置,但是 Python 中的 ssl 模块不可用。 (Windows 10)

python - 带有嵌套列表到 Dataframe 的字典

python - 如何解析包含不同对象类型的 HTML 表?

python - 如何在 osx 10.6.8 上安装 python 库 Pyexiv2 和 Gexiv2?

python - 制作一个可以同时运行两个Python脚本的Python脚本

python-3.x - 如何打印预测图像的置信度

python - 组合框不显示在 tkinter 中

python - tkinter 中是否可以有清晰/透明的标签?

python-3.x - tkinter,如何获取Entry小部件的值?

python - 通过python在csv文件的两列数据之间创建不同的组合/模式