Python 为什么要为此tkinter事件绑定调用多个函数?(已解决)

Python 为什么要为此tkinter事件绑定调用多个函数?(已解决),python,oop,tkinter,events,listbox,Python,Oop,Tkinter,Events,Listbox,下面的代码段创建了两个列表框。我编写了代码,以便: 从“可用”列表中选择的项目在单击该项目(通过OnASelect方法控制)时被传输到“选定”列表 传输项的索引保存在“可用”列表中(替换为空字符串) 从“选定”列表中选择的项目在单击该项目后会被传输回“可用”列表 因为“可用”列表的索引是保留的,所以无论单击的顺序如何,项目总是按原始顺序返回 这是我的问题: 尽管小部件按预期工作,但在将项目传输回“可用”列表时,我仍然会收到一个不必要的函数调用,从而导致索引错误。这个小部件是为我正在进行的一

下面的代码段创建了两个列表框。我编写了代码,以便:

  • 从“可用”列表中选择的项目在单击该项目(通过OnASelect方法控制)时被传输到“选定”列表
  • 传输项的索引保存在“可用”列表中(替换为空字符串)
  • 从“选定”列表中选择的项目在单击该项目后会被传输回“可用”列表
  • 因为“可用”列表的索引是保留的,所以无论单击的顺序如何,项目总是按原始顺序返回
这是我的问题:

  • 尽管小部件按预期工作,但在将项目传输回“可用”列表时,我仍然会收到一个不必要的函数调用,从而导致索引错误。这个小部件是为我正在进行的一个更大的项目设计的,我希望避免这会导致后续的问题
  • 为了进行故障排除,我编写了代码,以便在发生传输时,发送一条打印语句,显示“a>S函数已激活”或“S>a函数已激活”
  • 将项目从“可用”转移到“选定”时的输出:
  • 将项目从“选定”转移到“可用”时的输出:
我浪费了太多的时间试图弄清楚它为什么要这样做,我被难住了。在此问题上的任何帮助都将不胜感激

另外,我知道在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()
从tkinter导入*
类依赖列表(Tk):
定义初始化(自):
Tk.\uuuuuu初始(自我)
self.mainframe=Frame(self)
self.mainframe.place(relx=0.5,rely=0.25,anchor=CENTER)
completelabel=Label(self.mainframe,text=“可用:”)
completelabel.grid(行=2,列=0)
selectedlabel=Label(self.mainframe,text=“Selected:”)
selectedlabel.grid(行=2,列=1)
self.Available=Listbox(self.mainframe)
self.Available.grid(行=3,列=0)
self.AList=[]
对于范围(6)中的i:
self.Available.insert(结束,i)
self.AList.append(i)
self.Available.bind(“”,self.onselect)
self.Selected=Listbox(self.mainframe)
self.Selected.grid(行=3,列=1)
self.Selected.bind(“”,self.onselect)
def OnASelect(自我、事件):
打印('A>S功能已激活')
AselectionIndex=int(event.widget.curselection()[0])
Aselection=event.widget.get(AselectionIndex)
self.Available.delete(AselectionIndex)
self.Available.insert(AselectionIndex“”)
self.Selected.insert(结束,选择)
def OnSSelect(自我,事件):
打印('S>A功能已激活')
SselectionIndex=int(event.widget.curselection()[0])
Sselection=event.widget.get(SselectionIndex)
自我选择。删除(锚定)
self.Available.delete(self.AList.index(Sselection))
self.Available.insert(self.AList.index(Sselection),Sselection)
App=依赖列表()
screen_width=App.winfo_screenwidth()
屏幕高度=App.winfo屏幕高度()
窗口高度=屏幕高度-800
窗口宽度=屏幕宽度-1400
x_cordinate=int((屏幕宽度/2)-(窗口宽度/2))
y_cordinate=int((屏幕高度/2)-(窗口高度/2))
App.geometry(“{}x{}+{}+{}.”格式(窗口宽度、窗口高度、x坐标、y坐标))
App.mainloop()
编辑:解决方案在BryanOakley的答案(谢谢!)和该答案下的后续注释中。

在选择更改时触发。这可能发生在用户单击某个项目时,但也可能发生在其他时间,例如用户使用键盘遍历列表框,或者您的代码删除选定的内容


如果您的UI只在鼠标点击时工作,那么您应该绑定到它,而不是

如果项目从一个框到另一个框只在鼠标点击时发生,您是希望这种移动,还是希望用户能够使用键盘选择项目并将其从一侧移动到另一侧?@BryanOakley,在这种情况下,仅在mouseclicka上选择和mouseclick需要同时发生,因为如果我在列表框中的某个位置单击而不进行实际选择,我不希望这些方法运行。有没有办法做到这一点?@Elsayeda:选择是自动进行的,你不必做任何事情。如果您绑定到鼠标单击,您可以轻松地检查您是否在某个项目上,并允许或不允许选择。我认为mouseclick事件和我的方法中的后续代码在选择事件注册之前就已经运行,因为我在单击时会出现索引错误,并且直到我再做一个选择。在方法的其余部分之前使用条件“if self.Available.curselection():”是错误的解决方法,但我仍然必须双击才能进行传输(扩展来说,可以运行该方法两次)。选择确实是自动发生的,但为时已晚,我的代码无法使用它。“我认为mouseclick事件和我方法中的后续代码在选择事件注册之前就已经运行了”-是的,tkinter中的绑定就是这样工作的。听起来你不需要选择,你只需要知道点击的项目。您可以在不依赖选择的情况下获得。您可以执行类似于
event.widget.index(f“@{event.x},{event.y}”)
的操作来获取所单击项目的索引。这很有效!非常感谢。
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
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()