简体   繁体   English

与tkinter绑定时如何传递另一个参数?

[英]How can I pass another argument when binding with tkinter?

I just forayed into tkinter for the first time and am running into some issues. 我只是第一次涉足tkinter,并且遇到了一些问题。 I want to display several lists to users, and store their selections for each list in a dictionary (used to filter several columns of a dataframe later). 我想向用户显示多个列表,并将他们对每个列表的选择存储在字典中(以后用于过滤数据框的几列)。 Suppose, for instance, there are two lists: 1) One labeled "Brand", containing 'Brand X' and 'Brand Y' as options, 2) another "Customer Type", containing "New," "Existing," "All." 例如,假设有两个列表:1)一个标记为“ Brand”的列表,其中包含“ Brand X”和“ Brand Y”作为选项,2)另一个“ Customer Type”,其中包含“ New”,“ Existing”,“ All” “。

In sum, when all is said and done, if a user picks "Brand X", "New", and "All", then I'd get a dictionary back of {'Brand':['Brand X'],'Customer Type':['New','All']}. 总而言之,当一切都说完之后,如果用户选择“ Brand X”,“ New”和“ All”,那么我将得到{'Brand':['Brand X'],'的字典。客户类型”:['New','All']}。 Getting one list is easy... but looping through the lists is presenting problems. 获取一个列表很容易...但是遍历列表会带来问题。

I have the below code so far: 到目前为止,我有以下代码:

from tkinter import *
from tkinter import ttk


class checkList(Frame):
    def __init__(self, options, parent=None):
        Frame.__init__(self, parent)
        self.makeHeader()
        self.options = options
        self.pack(expand=YES, fill=BOTH, side=LEFT)
        self.makeWidgets(self.options)
        self.selections = []

    def makeHeader(self):
        header = ttk.Label(self,text='Please select options to limit on.')
        header.pack(side=TOP)
        self.header = header

    def makeWidgets(self, options):
        for key in self.options.keys():
            lbl = ttk.Label(self, text=key)
            lbl.pack(after=self.header)
            listbox = Listbox(self, selectmode=MULTIPLE, exportselection=0)
            listbox.pack(side=LEFT)
            for item in self.options[key]:
                listbox.insert(END, item)
            listbox.bind('<<ListboxSelect>>', self.onselect)
            self.listbox = listbox

    def onselect(self, event):
        selections = self.listbox.curselection()
        selections = [int(x) for x in selections]
        self.selections = [self.options[x] for x in selections]


if __name__ == '__main__':
    options = {'Brand':['Brand','Brand Y'], 'Customer Type': ['All Buyers','New Buyers','Existing Buyers']}
    checkList(options).mainloop()

Needless to say, the [self.options[x] for x in selections] works great with just one list, but since I have a dictionary, I really need [self.options[key][x] for x in selections]. 不用说,x的[self.options [x]]仅适用于一个列表,但是由于我有字典,所以我确实需要x的[self.options [key] [x]]。 However, I can't figure out how to pass the key at any given point in the loop. 但是,我不知道如何在循环中的任何给定点传递密钥。 Is there a way to achieve what I'm trying to do? 有没有办法实现我想要做的事情?

The "magic" you're looking for to pass the key is simple because the tkinter objects are extensible. 您正在寻找传递密钥的“魔术”很简单,因为tkinter对象是可扩展的。 Here's your code working, I believe, the way you want: 我相信,这是您想要的代码工作方式:

from tkinter import *
from tkinter import ttk


class checkList(Frame):
    def __init__(self, options, parent=None):
        Frame.__init__(self, parent)
        self.makeHeader()
        self.options = options
        self.pack(expand=YES, fill=BOTH, side=LEFT)
        self.listboxes = [] # New
        self.makeWidgets(self.options)
        self.selections = {} # Changed

    def makeHeader(self):
        header = ttk.Label(self,text='Please select options to limit on.')
        header.pack(side=TOP)
        self.header = header

    def makeWidgets(self, options):
        for key in self.options.keys():
            lbl = ttk.Label(self, text=key)
            lbl.pack(after=self.header)
            listbox = Listbox(self, selectmode=MULTIPLE, exportselection=0)
            listbox.key = key # here's the magic you were asking about...
            listbox.pack(side=LEFT)
            self.listboxes.append(listbox) # New
            for item in self.options[key]:
                listbox.insert(END, item)
            listbox.bind('<<ListboxSelect>>', self.onselect)
            self.listbox = listbox

    def onselect(self, event):
        for lb in self.listboxes:
            selections = lb.curselection()
            selections = [int(x) for x in selections]
            self.selections[lb.key] = [self.options[lb.key][x] for x in selections]
        print(self.selections)


if __name__ == '__main__': #   \/
    options = {'Brand':['Brand X','Brand Y'], 'Customer Type': ['All Buyers','New Buyers','Existing Buyers']}
    checkList(options).mainloop()

With the code you posted, you only have access to the last ListBox created by makeWidgets in onselect . 使用您发布的代码,您只能访问onselectmakeWidgets创建的最后一个ListBox

With minimal changes: 更改最少:

from tkinter import *
from tkinter import ttk

class checkList(Frame):
    def __init__(self, options, parent=None):
        Frame.__init__(self, parent)
        self.listboxes = []
        self.selections = {}
        self.makeHeader()
        self.options = options
        self.pack(expand=YES, fill=BOTH, side=LEFT)
        self.makeWidgets(self.options)

    def makeHeader(self):
        header = ttk.Label(self,text='Please select options to limit on.')
        header.pack(side=TOP)
        self.header = header

    def makeWidgets(self, options):
        for key in self.options.keys():
            lbl = ttk.Label(self, text=key)
            lbl.pack(after=self.header)
            listbox = Listbox(self, selectmode=MULTIPLE, exportselection=0)
            listbox.pack(side=LEFT)
            for item in self.options[key]:
                listbox.insert(END, item)
            listbox.bind('<<ListboxSelect>>', self.onselect)
            self.listboxes.append(listbox)

    def onselect(self, event):
        for (option, options), listbox in zip(self.options.items(), self.listboxes):
            self.selections[option] = [options[x] for x in map(int, listbox.curselection())]
        print(self.selections)

if __name__ == '__main__':
    options = {'Brand':['Brand','Brand Y'], 'Customer Type': ['All Buyers','New Buyers','Existing Buyers']}
    checkList(options).mainloop()

This recreates selections every time either ListBox selection is modified. 每次修改ListBox选择时,都会重新创建selections Alternatively, you could use event to determine which ListBox selection was modified and update the corresponding part of selections . 或者,您可以使用event来确定修改了哪个ListBox选择并更新selections的相应部分。 This would require initializing selections , though. 不过,这将需要初始化selections

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM