Tkinter ListboxSelect 回调总是处理列表中的最后一项
Tkinter ListboxSelect callback always processes last item in the list
如果在未选择条目的情况下执行 ListboxSelect 回调,即在相应列表框中的单击已放置在空 space 中最后一项的下方,“curselection”方法始终 returns 列表框中最后一项的索引。更重要的是,如果尝试使用列表框的默认“浏览”选择方法并在按住鼠标按钮的同时将鼠标光标移到列表框上,则任何移动都会执行回调。我试图找到有关如何修复它的提示...不过运气不好。
from tkinter import *
class simple( Frame ):
def __init__( self, parent = None ):
Frame.__init__( self )
self.master.title( 'DEMO' )
self.master.bind( '<Control-q>', quit )
self.pack()
self.create_widgets()
def create_widgets( self ):
words = ['An','"empty"','selection','processes','the', 'last', 'item','in','this','list' ]
self.lb = Listbox ( self, width = 12, height = 25, selectmode = SINGLE, exportselection = False )
self.lb.pack ( side = LEFT )
self.lb.bind ( '<<ListboxSelect>>', self.process_item )
Label ( self, anchor = W, text = '\n\nClick here\n\n<--\n\nin the emtpy space...' ).pack ( side = RIGHT )
for w in words:
self.lb.insert ( 0, w )
def process_item ( self, event ):
selection = self.lb.curselection ( )
self.do_stuff_with_item ( self.lb.get ( selection ) )
self.lb.delete ( selection )
def do_stuff_with_item ( self, item ):
print ( item )
def engage():
root = Tk()
sw = simple( root )
sw.pack()
root.mainloop()
if __name__ == '__main__':
engage()
我用 python 2.7、3.6(在 Linux 上)和 python 3.8 在 Win
上试过
实现您的要求确实很棘手。
Listbox
的默认行为是 select 获得焦点时的最后一项。
为了愚弄它,您可以添加一个空词作为您的 words
列表的最后一项。
这将使它在 Listbox
中不可见。
然后在您的 process_item
回调中,检查 selected 值是否为空(可选,如果它也是最后一个值)。如果是这样,请从您的回调中移除 Listbox
和 return 的焦点。这看起来好像什么都没发生。
这里是修改后的代码:
from tkinter import *
class simple(Frame):
def __init__(self, parent=None):
Frame.__init__(self)
self.master.title('DEMO')
self.master.bind('<Control-q>', quit)
self.pack()
self.create_widgets()
def create_widgets(self):
# Words with dummy "" word in the end
words = ['An', '"empty"', 'selection', 'processes', 'the', 'last', 'item', 'in', 'this', 'list', ""]
self.lb = Listbox(self, width=12, height=25, selectmode=SINGLE, exportselection=False)
self.lb.pack(side=LEFT)
self.lb.bind('<<ListboxSelect>>', self.process_item)
Label(self, anchor=W, text='\n\nClick here\n\n<--\n\nin the emtpy space...').pack(side=RIGHT)
self.lb.insert(0, *words)
def process_item(self, event):
selection = self.lb.curselection()
item = self.lb.get(selection)
if item == "":
# It's last dummy item, remove focus and return
self.master.after(0, self.master.focus)
return
# Real item was clicked
self.do_stuff_with_item(item)
self.lb.delete(selection)
def do_stuff_with_item(self, item):
print(item)
def engage():
root = Tk()
sw = simple(root)
sw.pack()
root.mainloop()
if __name__ == '__main__':
engage()
如果在未选择条目的情况下执行 ListboxSelect 回调,即在相应列表框中的单击已放置在空 space 中最后一项的下方,“curselection”方法始终 returns 列表框中最后一项的索引。更重要的是,如果尝试使用列表框的默认“浏览”选择方法并在按住鼠标按钮的同时将鼠标光标移到列表框上,则任何移动都会执行回调。我试图找到有关如何修复它的提示...不过运气不好。
from tkinter import *
class simple( Frame ):
def __init__( self, parent = None ):
Frame.__init__( self )
self.master.title( 'DEMO' )
self.master.bind( '<Control-q>', quit )
self.pack()
self.create_widgets()
def create_widgets( self ):
words = ['An','"empty"','selection','processes','the', 'last', 'item','in','this','list' ]
self.lb = Listbox ( self, width = 12, height = 25, selectmode = SINGLE, exportselection = False )
self.lb.pack ( side = LEFT )
self.lb.bind ( '<<ListboxSelect>>', self.process_item )
Label ( self, anchor = W, text = '\n\nClick here\n\n<--\n\nin the emtpy space...' ).pack ( side = RIGHT )
for w in words:
self.lb.insert ( 0, w )
def process_item ( self, event ):
selection = self.lb.curselection ( )
self.do_stuff_with_item ( self.lb.get ( selection ) )
self.lb.delete ( selection )
def do_stuff_with_item ( self, item ):
print ( item )
def engage():
root = Tk()
sw = simple( root )
sw.pack()
root.mainloop()
if __name__ == '__main__':
engage()
我用 python 2.7、3.6(在 Linux 上)和 python 3.8 在 Win
上试过实现您的要求确实很棘手。
Listbox
的默认行为是 select 获得焦点时的最后一项。
为了愚弄它,您可以添加一个空词作为您的 words
列表的最后一项。
这将使它在 Listbox
中不可见。
然后在您的 process_item
回调中,检查 selected 值是否为空(可选,如果它也是最后一个值)。如果是这样,请从您的回调中移除 Listbox
和 return 的焦点。这看起来好像什么都没发生。
这里是修改后的代码:
from tkinter import *
class simple(Frame):
def __init__(self, parent=None):
Frame.__init__(self)
self.master.title('DEMO')
self.master.bind('<Control-q>', quit)
self.pack()
self.create_widgets()
def create_widgets(self):
# Words with dummy "" word in the end
words = ['An', '"empty"', 'selection', 'processes', 'the', 'last', 'item', 'in', 'this', 'list', ""]
self.lb = Listbox(self, width=12, height=25, selectmode=SINGLE, exportselection=False)
self.lb.pack(side=LEFT)
self.lb.bind('<<ListboxSelect>>', self.process_item)
Label(self, anchor=W, text='\n\nClick here\n\n<--\n\nin the emtpy space...').pack(side=RIGHT)
self.lb.insert(0, *words)
def process_item(self, event):
selection = self.lb.curselection()
item = self.lb.get(selection)
if item == "":
# It's last dummy item, remove focus and return
self.master.after(0, self.master.focus)
return
# Real item was clicked
self.do_stuff_with_item(item)
self.lb.delete(selection)
def do_stuff_with_item(self, item):
print(item)
def engage():
root = Tk()
sw = simple(root)
sw.pack()
root.mainloop()
if __name__ == '__main__':
engage()