ttk.Combobox 在不同 tk.Listbox 中触发 <<ListboxSelect>> 事件

ttk.Combobox triggers <<ListboxSelect>> event in different tk.Listbox

我正在尝试做的事情: 我正在尝试在 Python 中使用 tkinter 构建一个 GUI(我在 [=57= 上使用版本 3.7.7 ]) 的主要 window 有一个列表框,第二个 window 包含一个组合框。 在列表框中可以打开不同的文件。单击每个条目时,主要 window 中会显示一些附加信息(该部分不在我下面较短的示例代码中)。所以我所做的是将列表框绑定到一个函数,该函数使用 <<ListboxSelect>> 事件加载和显示信息(下面代码中的 function_1)。 第二个 window 可以用一个按钮打开,应该编辑 selected 文件。在第二个 window 的组合框中,有不同的选项可以根据 select 编辑的内容更改第二个 window 的其他元素。这就是为什么我将 <<ComboboxSelected>> 事件绑定到另一个函数(下面代码中的 function_2)。

我的问题是: 当我 select 第二个 window 的组合框中的值时,第一个函数绑定到第一个 window 的列表框在组合框的正确功能之后执行。这只会在组合框的值第一次被 selected 时发生,每次创建第二个 window 时。此外,当查看列表框的 selected 值时,它 returns 组合框的 selected 值。

编辑: 我刚刚注意到这个问题只发生在我之前 select 在列表框中输入一个项目时。所以就像我在下面说的那样,它可能与列表框仍然处于活动状态或类似的事情有关。

我的代码和一个例子:

import tkinter as tk
from tkinter import ttk


class MainGUI:
    def __init__(self):
        self.root = tk.Tk()

        items = ['Test 1', 'Test 2', 'Test 3']

        self.item_box = tk.Listbox(self.root)
        self.item_box.insert('end', *items)
        self.item_box.bind('<<ListboxSelect>>', self.function_1)
        self.item_box.pack()
        tk.Button(self.root, text='Open second window',
                  command=self.open_window).pack()

        self.root.mainloop()

    def function_1(self, event):
        print('MainGUI function:', event)
        print('Text in Listbox:', self.item_box.selection_get())

    def open_window(self):
        SecondGUI()


class SecondGUI:
    def __init__(self):
        self.window = tk.Toplevel()
        self.window.grab_set()

        items = ['A', 'B', 'C']

        self.dropdown = ttk.Combobox(self.window, values=items)
        self.dropdown.current(0)
        self.dropdown.pack()
        self.dropdown.bind('<<ComboboxSelected>>', self.function_2)

    def function_2(self, event):
        print('SecondGUI function:', event)


MainGUI()

Image of the GUI before and after the option B is clicked

selecting Test 1、使用按钮打开第二个 window 和 selecting B 后的输出如下所示:

MainGUI function: <VirtualEvent event x=0 y=0>
Text in Listbox: Test 1
SecondGUI function: <VirtualEvent event x=0 y=0>
MainGUI function: <VirtualEvent event x=0 y=0>
Text in Listbox: B

我的猜测: 如果我不得不猜测问题出在哪里,我会说 Combobox 中可能有某种发送事件的列表框,但正如我无法找到有关这些事件何时以及如何发送的更多信息,我真的找不到任何相关信息(编辑:不太可能)。查看图片时,您可以看到第一个 window 中的条目仍然 selected 直到第二个 window 中的条目被单击,所以我的第二个猜测是列表框仍处于活动状态,并在单击时采用新的 selected 值或类似的东西(编辑:更有可能)。

我的问题:为什么当我在不同的 window 中使用不同的小部件时第一个函数会执行,我该如何解决这个问题,或者有更好的方法首先如何做到这一点?

TL;DR: 当组合框 select 在不同的 window 中编辑时,列表框会收到一个事件。为什么?

提前致谢!

可能是因为ListboxCombobox都没有设置exportselection=False。 So when an item in the Combobox is selected, it will clear the selection of Listbox which triggers the <<ListboxSelect>> event.

您还使用了错误的函数 self.item_box.selection_get() 来获取 Listbox 的当前选定项。 self.item_box.get(self.item_box.curselection()) 应该改用。

以下更改应该可以解决问题:

class MainGUI:
    def __init__(self):
        ...
        self.item_box = tk.Listbox(self.root, exportselection=False)
        ...

    def function_1(self, event):
        print('MainGUI function:', event)
        print('Text in Listbox:', self.item_box.get(self.item_box.curselection()))

    ...

class SecondGUI:
    def __init__(self):
        ...
        self.dropdown = ttk.Combobox(self.window, values=items, exportselection=False)
        ...

    ...