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 中编辑时,列表框会收到一个事件。为什么?
提前致谢!
可能是因为Listbox
和Combobox
都没有设置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)
...
...
我正在尝试做的事情: 我正在尝试在 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 中编辑时,列表框会收到一个事件。为什么?
提前致谢!
可能是因为Listbox
和Combobox
都没有设置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)
...
...