python - 为什么要为此 tkinter 事件绑定调用多个函数?(解决了)
问题描述
下面的代码片段创建了两个列表框。我编写了代码,以便:
- 单击该项目后,从“可用”列表中选择的项目将传输到“已选择”列表(通过 OnASelect 方法控制)
- 传输的项目的索引保存在“可用”列表中(它被替换为空字符串)
- 单击该项目后,从“已选择”列表中选择的项目将转移回“可用”列表
- 因为保留了“可用”列表的索引,所以无论单击什么顺序,项目总是按原始顺序传回。
这是我的问题:
- 尽管小部件按预期工作,但在将项目返回到“可用”列表时,我仍然会收到对 OnASelect 的不必要的函数调用,这会导致索引错误。这个小部件适用于我正在处理的一个更大的项目,我想避免这导致问题。
- 出于故障排除的目的,我编写了代码,以便在发生传输时发送打印语句,显示“A>S 功能已激活”或“S>A 功能已激活”。
- 将项目从“可用”转移到“已选择”时的输出:
The A>S function was activated
- 将项目从“选定”转移到“可用”时的输出:
The S>A function was activated
The A>S function was activated
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "x:/Mouselight Data Management/GUI_Branch/GUI_Menu_Related/Test/test2.py", line 29, in OnASelect
AselectionIndex = int(event.widget.curselection()[0])
IndexError: tuple index out of range
PS X:\Mouselight Data Management\GUI_Branch> The A>S function was activate
我浪费了太多时间试图弄清楚为什么会这样,我很困惑。对此问题的任何帮助将不胜感激!
附言。我知道在 OnASelect 方法的开头添加一个 'if event.widget.curselection():' 会绕过错误,但我想阻止多个函数调用开始。
完整代码:
from tkinter import *
class DependentLists(Tk):
def __init__(self):
Tk.__init__(self)
self.mainframe = Frame(self)
self.mainframe.place(relx=0.5, rely=0.25, anchor=CENTER)
completelabel = Label(self.mainframe, text = "Available:")
completelabel.grid(row=2, column = 0)
selectedlabel = Label(self.mainframe, text = "Selected:")
selectedlabel.grid(row=2, column = 1)
self.Available = Listbox(self.mainframe)
self.Available.grid(row=3, column = 0)
self.AList = []
for i in range(6):
self.Available.insert(END,i)
self.AList.append(i)
self.Available.bind('<<ListboxSelect>>', self.OnASelect)
self.Selected = Listbox(self.mainframe)
self.Selected.grid(row=3, column = 1)
self.Selected.bind('<<ListboxSelect>>', self.OnSSelect)
def OnASelect(self, event):
print('The A>S function was activated')
AselectionIndex = int(event.widget.curselection()[0])
Aselection = event.widget.get(AselectionIndex)
self.Available.delete(AselectionIndex)
self.Available.insert(AselectionIndex,'')
self.Selected.insert(END, Aselection)
def OnSSelect(self, event):
print('The S>A function was activated')
SselectionIndex = int(event.widget.curselection()[0])
Sselection = event.widget.get(SselectionIndex)
self.Selected.delete(ANCHOR)
self.Available.delete(self.AList.index(Sselection))
self.Available.insert(self.AList.index(Sselection), Sselection)
App = DependentLists()
screen_width = App.winfo_screenwidth()
screen_height = App.winfo_screenheight()
window_height = screen_height - 800
window_width = screen_width - 1400
x_cordinate = int((screen_width/2) - (window_width/2))
y_cordinate = int((screen_height/2) - (window_height/2))
App.geometry("{}x{}+{}+{}".format(window_width, window_height, x_cordinate, y_cordinate))
App.mainloop()
编辑:解决方案在 BryanOakley 的回答中(谢谢!)以及该答案下的后续评论。
解决方案
<<ListboxSelect>>
is triggered whenever the selection changes. 这可能发生在用户单击某个项目时,但也可能发生在其他时间,例如用户使用键盘遍历列表框,或者您的代码删除了选定的内容。
如果你的 UI 应该只在鼠标点击时工作,你应该绑定到那个而不是<<ListboxSelect>>
.
推荐阅读
- python - 如何将 .py 转换为 .exe 及其所有依赖项
- regex - 正则表达式匹配带有通配符的子字符串
- java - 这是 LinkedList 的正确可视化吗?
- c - Freeswitch 是否支持从传入的 3PCC INVITE 生成 SRTP 报价?
- maven - 将 google-cloud-storage 添加到 maven - NoClassDefFoundError
- c# - 为什么 Selenium 的 Internet Explorer 驱动程序偶尔无法保持与 Web 驱动程序服务器的连接?
- c# - IIS 8.5 (Windows Server 2012 R2) 上的 Blazor 不起作用。任何想法下一步该做什么?
- binary - 在 fortran 中写一个原始的二进制无符号 32 位整数
- javascript - 将变量从php发送到js ajax
- c++ - 模板的超类
Foo 类