Stacked Widgets触发他们自己的事件

时间:2017-06-13 14:03:13

标签: python python-3.x tkinter

我在事件处理程序上使用绑定时遇到问题。

我在mainFrame上放置了两个堆叠的框架。每个框架都有自己的按钮。当我单击一个按钮时,相关的框架被抬起。

在每个帧上,我有一个列表框。这些列表框位于mainFrame上的相同位置。当我在第一个列表框中选择一个项目时,它会使用新内容填充另一个列表框。然后我单击第二帧按钮以访问我的第二个列表框。我复制(使用新名称)事件与我的第二个列表框完全相同,以填充第三个列表框。

然而,当我在第二个列表框中选择一个项目时,似乎第一个列表框的事件也被触发但只有一次(如果我重做我的选择它只触发第二个列表框的事件)。

编辑:我根据要求提供了我的代码的“简短”版本。

当我选择db1或db2时,它是第一个列表框,框架2被抬起并打印 test2 。然后我选择item1或item2,同时打印 test2 / test1 而不是 test1

from tkinter import *

class Page(Frame):
    def __init__(self, *args, **kwargs):
        Frame.__init__(self, *args, **kwargs)
    def show(self):
        self.lift()

class Page1(Page):

    def dbCheckCommand(self, event, page2):
        page2.collections.delete(0, END)
        print("test2")
        page2.collections.insert(END, "item1")
        page2.collections.insert(END, "item2")

    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        self.grid_columnconfigure(0, weight=1)
        self.databases = Listbox(self, height=2)
        self.grid_rowconfigure(1, weight=1)
        self.databases.insert(END, "db1")
        self.databases.insert(END, "db2")
        self.databases.grid(row=1, sticky="nsew")

class Page2(Page):
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        self.grid_columnconfigure(0, weight=1)
        self.colls = []
        self.collections = Listbox(self, height=2)
        self.grid_rowconfigure(1, weight=1)
        self.collections.grid(row=1, sticky="nsew")

class MainView(Frame):

    def on_p1_listbox_selection(self, event, page1, page2):
        page1.dbCheckCommand(event, page2)
        page2.lift()

    def on_p2_listbox_selection(self, event):
        print("test1")

    def __init__(self, *args, **kwargs):
        Frame.__init__(self, *args, **kwargs)

        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(1, weight=5)
        buttonframe = Frame(self)
        container = Frame(self)
        buttonframe.grid(column=0, row=0, sticky="nsew")

        container.grid(column=1, row=0, sticky="nsew")
        container.grid_columnconfigure(0, weight=1)
        container.grid_rowconfigure(0, weight=1)

        p1 = Page1(container)
        p2 = Page2(container)

        p1.grid(column=0, row=0, sticky="nsew")
        p2.grid(column=0, row=0, sticky="nsew")


        b1 = Button(buttonframe, text="1 - Server & Database", command=p1.lift)
        b2 = Button(buttonframe, text="2 - Collection", command=p2.lift)

        b1.pack(fill="both", expand=1)
        b2.pack(fill="both", expand=1)


        p1.databases.bind("<<ListboxSelect>>", lambda event: self.on_p1_listbox_selection(event, p1, p2))
        p2.collections.bind("<<ListboxSelect>>", lambda event: self.on_p2_listbox_selection(event))

        p1.show()


if __name__ == "__main__":
    root = Tk()
    main = MainView(root)
    main.pack(fill="both", expand=1)
    root.wm_geometry("1100x500")
    root.wm_title("MongoDB Timed Sample Generator")
    root.mainloop()

1 个答案:

答案 0 :(得分:3)

只要选择更改,<<ListboxSelect>>事件就会触发。这意味着在进行新选择时,或者取消选择当前选择时。

默认情况下,列表框中的所选项目将导出到X selection。由于始终只能有一个 X选择,因此当您在一个列表框中选择一个项目时,将取消选择任何其他列表框。因此,当您单击第二个列表框中的某个项目时,第一个列表框的选择将会丢失,并导致<<ListboxSelect>>事件被发送。

一个简单的解决方案是在列表框中关闭此行为,以便您可以同时在每个列表框中选择一些内容。您可以通过在每个列表框中将exportselection标记设置为False来完成此操作。

例如:

self.databases = Listbox(..., exportselection=False)
...
self.collections = Listbox(..., exportselection=False)