在列表框中获取所选项目并调用另一个存储所选项目的函数

时间:2011-09-30 22:03:43

标签: python listbox tkinter tk

我有一个在点击时调用createCategoryMeny(x)的画布。

此功能只创建一个Toplevel()窗口,

def createCategoryMenu(tableNumber):

    ##Not interesting below:
    categoryMenu = Toplevel()
    categoryMenu.title("Mesa numero: " + str(tableNumber))
    categoryMenu.geometry("400x400+100+100")

    categoryMenu.focus()
    categoryMenu.grab_set()

    Label(categoryMenu, text="Elegir categoria \n Mesa numero: " + str(tableNumber)).pack()


    ## RELEVANT CODE BELOW:
    listbox = Listbox(categoryMenu, width=50, height=len(info.listaCategorias))
    listbox.pack(pady=20)

    for item in info.listaCategorias:
        listbox.insert(END, item)

    listbox.selection_set(first=0)

    ##My attempt to solve it
    callback = lambda event, tag= "ThisShouldBeTheSelected!!": do(event, tag)
    listbox.bind("<Double-Button-1>", callback)

然后是do函数:

def do(event, tag):
    print tag

这成功地打印了“ThisShouldBeTheSelected !!”``。

这就是我完全陷入困境的地方。

我无法获得双击元素(所选元素)。

我想将其作为tag=传递。

我试过了:

listbox.curselection()

始终打印('0',)

如果我删除listbox.selection_set(first=0),我只会这样:()

所以问题是:

  • 如何获取所选项目(双击的项目)
  • (不是那么重要)将它传递给我的其他功能是否合理?

注意:

我找到this

  

8.5。为什么没有.listbox curselection或选择返回   当我将一个按钮绑定到我的列表框时,是否有适当的项目?

     

在按钮点击事件期间获取所选项目的最佳方法   listbox将使用以下代码:

     

bind .listbox {set item [%W get [%W nearest%y]]}

     

这可确保指针下的项目将返回   作为项目。 .listbox curselection失败的原因是因为   直到Listbox类绑定时才会设置curselection中的项目   触发器,默认情况下在实例绑定之后。这是   选择获得的原因与失败相同,但也会失败   如果将-exportselection选项设置为0,则会失败。

我不确定它是否有用,我真的不明白它的含义。

3 个答案:

答案 0 :(得分:15)

首先,不要使用lambda。它对于一小部分问题很有用,而这不是其中之一。创建一个合适的函数,它们更容易编写和维护。

完成后,您可以致电curselection获取当前选择。你说你试过了,但是你的示例代码没有显示你尝试的内容,所以我只能假设你做错了。

至于使用nearest的相当不同寻常的建议...所有它说的是你放在一个小部件上的绑定发生在同一事件的默认绑定之前。它是设置选择的默认绑定,因此当您绑定到单个按钮时,绑定将在默认绑定更新选择之前触发。有很多方法,其中最好的方法是一次点击绑定,而是绑定<<ListboxSelect>>,这将在选择更改后触发。

然而,你没有这个问题。由于您在双击时绑定,因此选择将由默认的单击绑定设置,curselection将返回正确的值。也就是说,除非您有自己的单击绑定,否则会阻止默认绑定触发。

这是一个打印出选择的简单示例,因此您可以看到它是正确的。从命令行运行它,以便您看到stdout:

import Tkinter as tk

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        lb = tk.Listbox(self)
        lb.insert("end", "one")
        lb.insert("end", "two")
        lb.insert("end", "three")
        lb.bind("<Double-Button-1>", self.OnDouble)
        lb.pack(side="top", fill="both", expand=True)

    def OnDouble(self, event):
        widget = event.widget
        selection=widget.curselection()
        value = widget.get(selection[0])
        print "selection:", selection, ": '%s'" % value

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

答案 1 :(得分:0)

对于spyder和python 3.6,以下代码有效。

import tkinter as tk
root = tk.Tk()
root.geometry("612x417")
root.title("change label on listbox selection")
root.resizable(0,0)
root.configure(background='lightgrey')


#Show selected currency for from in label
frmcur_text = tk.StringVar()
frmcur = tk.Label(root, textvariable=frmcur_text, font="Helvetica 10 bold", anchor='w', background='lightgrey').place(x=195,y=50)

def onselect(evt):
    # Note here that Tkinter passes an event object to onselect()

    w = evt.widget
    index = int(w.curselection()[0])
    value = w.get(index)
#    print ('You selected item %d: "%s"' % (index, value))
    frmcur_text.set(value)

#Create listboxes for xurrency selection
listbox1 = tk.Listbox(root, font="Helvetica 11 bold", height=3, width=10)
listbox2 = tk.Listbox(root, font="Helvetica 11 bold", height=3, width=10)
listbox1.place(x=300,y=50)
listbox2.place(x=300,y=125)


for i in range(20):
    i = i + 1
    listbox1.insert(1, i)
    listbox2.insert(1, i)


listbox1.bind('<<ListboxSelect>>', onselect)    

cs = listbox1.curselection()

frmcur_text.set(cs)

root.mainloop()

答案 2 :(得分:0)

虽然您只有一个要管理的列表框,但使用此类内容(Python 3)非常好:

import tkinter as tk

root = tk.Tk()
box = tk.Listbox(root)
box.insert(tk.END, 'First')
box.insert(tk.END, 'Second')
box.insert(tk.END, 'Third')
box.pack()


def onselect(event):
    w = event.widget
    idx = int(w.curselection()[0])
    value = w.get(idx)
    print(value)


box.bind('<<ListboxSelect>>', onselect)

root.mainloop()

但是当您添加另一个列表框或\并遇到情况时,listbox会丢失其选择,会引发IndexError。 为了避免它,并为不同的列表框管理不同的回调,我建议这样的事情:

import tkinter as tk

root = tk.Tk()
box = tk.Listbox(root)
box.insert(tk.END, 'First')
box.insert(tk.END, 'Second')
box.insert(tk.END, 'Third')
box.pack()

box2 = tk.Listbox(root)
box2.insert(tk.END, 'First')
box2.insert(tk.END, 'Second')
box2.insert(tk.END, 'Third')
box2.pack()


def on_first_box(idx, val):
    print('First box idx: %s, value: %s' % (idx, val))


def on_second_box(idx, val):
    print('Second box idx: %s, value: %s' % (idx, val))


def onselect(event, listbox):
    w = event.widget
    try:
        idx = int(w.curselection()[0])
    except IndexError:
        return
    if listbox is box:
        return on_first_box(idx, w.get(idx))
    if listbox is box2:
        return on_second_box(idx, w.get(idx))


box.bind('<<ListboxSelect>>', lambda e: onselect(e, box))
box2.bind('<<ListboxSelect>>', lambda e: onselect(e, box2))

root.mainloop()