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

Posted

技术标签:

【中文标题】获取列表框中的选定项目并调用另一个存储选定项目的函数【英文标题】:Get selected item in listbox and call another function storing the selected for it 【发布时间】:2011-11-28 19:32:47 【问题描述】:

我有一个画布,当它被点击时会调用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 或 selection 不返回 当我将按钮绑定到我的列表框时正确的项目?

在按钮单击事件期间获取所选项目的最佳方式 listbox就是使用如下代码:

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

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

我不确定它是否有帮助,我不太明白它在说什么。

【问题讨论】:

【参考方案1】:

虽然您只有一个要管理的列表框,但使用这样的东西(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()

但是当您添加另一个列表框,或者\遇到列表框失去选择的情况时,会引发 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()

【讨论】:

【参考方案2】:

对于 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()

【讨论】:

【参考方案3】:

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

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

至于使用nearest 的相当不寻常的建议......它只是说您在小部件上的绑定发生在同一事件的默认绑定之前。它是设置选择的默认绑定,因此当您绑定到 single 按钮单击时,您的绑定会在默认绑定更新选择之前触发。有很多方法可以解决这个问题,其中最好的方法是单击一次绑定,而是绑定&lt;&lt;ListboxSelect&gt;&gt;,这将在选择更改后触发。

但是,您没有这个问题。由于您是通过双击绑定的,因此默认的单击绑定将设置选择,curselection 将返回正确的值。也就是说,除非您有自己的单击绑定来阻止默认绑定触发。

这是一个简单的示例,它打印出选择,以便您可以看到它是正确的。从命令行运行它,你会看到标准输出:

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()

【讨论】:

为 > 加一个 - 我正在寻找那种事件。 那么函数应该是什么样子,这些答案对我来说让尝试和实现变得更加混乱 @GoulouhAnwar:what 函数应该是什么样的?你说的是什么功能? “首先,不要使用 lambda。它对范围很窄的问题很有用,而这不是其中之一。创建一个合适的函数,它们更容易编写和维护。” @GoulouhAnwar:这个答案不使用 lambda,它非常具体地向您展示了如何使用普通函数 (OnDouble) 而不是 lambda。你还需要看什么?

以上是关于获取列表框中的选定项目并调用另一个存储选定项目的函数的主要内容,如果未能解决你的问题,请参考以下文章

如何根据另一个的选定项目过滤一个组合框集合?

在不使用导航链接的情况下获取 SwiftUI 列表中的选定项目

是否可以将 listBox 选定的项目从一个 wpf 页面传递到另一个页面

WPF ListBox 值来自另一个选定的 ListBox 项,然后上下移动

删除列表框中的多个选定项目 - 仅识别第一个选择的代码

保存列表框中的选定项目以供其他类使用