我正在为多列表框(http://code.activestate.com/recipes/52266-multilistbox-tkinter-widget/)使用代码
这是在创建供用户选择的数据列,当用户列表框选择将记录中的列填充到不同的“输入”框中时。
我可以在函数中使用.bind .delete .insert使其在标准列表框中工作,但由于字典中的数据大小不同,因此看起来很丑陋:)
我真的很想坚持下面的代码,但是我无法使该功能正常工作。真的很感激有人能指出我正确的方向,试图解决这几天但绕圈走动
我想解析的代码
def on_selection(event):
line = event.widget.get(event.widget.curselection())
locationent.delete(0, 'end')
cuspnent.delete(0, 'end')
locationent.insert('end', line[0:1])
cuspnent.insert('end', line[1:2])
if __name__ == '__main__':
ttk.Label(leftbottomframe, text='**Select count record from MultiListbox by doubleclick**').pack()
mlb = MultiListbox(leftbottomframe, (('Location', 15),('RRD PN', 15),("Lot/Serial", 15), ('Description', 35), ('Customer PN', 15)))
for i in dic:
mlb.insert(END, (dic[i]['Location'],dic[i]['Item Number'],dic[i]['Lot/Serial'],dic[i]['Description'],dic[i]['Cross_Reference']))
mlb.bind('<<ListboxSelect>>', on_selection)
用于多列表框的更大代码集
data_file= pd.read_excel('CC 180763.xlsx',sheet_name='Sheet1',header=0,converters={'Location':str,'Item Number':str,'Cross_Reference':str,'Description':str})
print (data_file)
dic = data_file.set_index('Reference').transpose().to_dict(orient='dict')# data_file.to_dict(orient='records')
class MultiListbox(Frame):
def __init__(self, master, lists):
Frame.__init__(self, master)
self.lists = []
for l, w in lists:
frame = Frame(self);
frame.pack(side=LEFT, expand=YES, fill=BOTH)
Label(frame, text=l, borderwidth=1, relief=RAISED).pack(fill=X)
lb = Listbox(frame, width=w, borderwidth=0, selectborderwidth=0,
relief=FLAT, exportselection=FALSE)
lb.pack(expand=YES, fill=BOTH)
self.lists.append(lb)
lb.bind('<B1-Motion>', lambda e, s=self: s._select(e.y))
lb.bind('<Button-1>', lambda e, s=self: s._select(e.y))
lb.bind('<Leave>', lambda e: 'break')
lb.bind('<B2-Motion>', lambda e, s=self: s._b2motion(e.x, e.y))
lb.bind('<Button-2>', lambda e, s=self: s._button2(e.x, e.y))
frame = Frame(self);
frame.pack(side=LEFT, fill=Y)
ttk.Label(frame, borderwidth=1, relief=RAISED).pack(fill=X)
sb = Scrollbar(frame, orient=VERTICAL, command=self._scroll)
sb.pack(expand=YES, fill=Y)
self.lists[0]['yscrollcommand'] = sb.set
def _select(self, y):
row = self.lists[0].nearest(y)
self.selection_clear(0, END)
self.selection_set(row)
return 'break'
def _button2(self, x, y):
for l in self.lists: l.scan_mark(x, y)
return 'break'
def _b2motion(self, x, y):
for l in self.lists: l.scan_dragto(x, y)
return 'break'
def _scroll(self, *args):
for l in self.lists:
apply(l.yview, args)
def curselection(self):
return self.lists[0].curselection()
def delete(self, first, last=None):
for l in self.lists:
l.delete(first, last)
def get(self, first, last=None):
result = []
for l in self.lists:
result.append(l.get(first, last))
if last: return apply(map, [None] + result)
return result
def index(self, index):
self.lists[0].index(index)
def insert(self, index, *elements):
for e in elements:
i = 0
for l in self.lists:
l.insert(index, e[i])
i = i + 1
def size(self):
return self.lists[0].size()
def see(self, index):
for l in self.lists:
l.see(index)
def selection_anchor(self, index):
for l in self.lists:
l.selection_anchor(index)
def selection_clear(self, first, last=None):
for l in self.lists:
l.selection_clear(first, last)
def selection_includes(self, index):
return self.lists[0].selection_includes(index)
def selection_set(self, first, last=None):
for l in self.lists:
l.selection_set(first, last)
def on_selection(event):
line = event.widget.get(event.widget.curselection())
locationent.delete(0, 'end')
cuspnent.delete(0, 'end')
locationent.insert('end', line[0:1])
cuspnent.insert('end', line[1:2])
if __name__ == '__main__':
ttk.Label(leftbottomframe, text='**Select count record from MultiListbox by doubleclick**').pack()
mlb = MultiListbox(leftbottomframe, (('Location', 15),('RRD PN', 15),("Lot/Serial", 15), ('Description', 35), ('Customer PN', 15)))
for i in dic:
mlb.insert(END, (dic[i]['Location'],dic[i]['Item Number'],dic[i]['Lot/Serial'],dic[i]['Description'],dic[i]['Cross_Reference']))
mlb.bind('<<ListboxSelect>>', on_selection)
mlb.pack(expand=YES, fill=BOTH)
答案 0 :(得分:1)
问题:当用户列表框选择填充记录中的列时
删除它,因为它绑定到Frame
,所以这不是您想要的。
#mlb.bind('<<ListboxSelect>>', on_selection)
将以下内容添加到class MultiListbox
:
class MultiListbox(Frame):
def __init__(self, master, lists):
Frame.__init__(self, master)
self.labels = []
...
for l, w in lists:
self.labels.append(l)
lb.bind('<<ListboxSelect>>', self.on_selection)
...
删除以下内容,因为绑定任何B1...
将阻止<<ListboxSelect>>
事件。
注意:如果否则需要这些绑定,则必须链接到
self.on_selection
。
#lb.bind('<B1-Motion>', lambda e, s=self: s._select(e.y))
#lb.bind('<Button-1>', lambda e, s=self: s._select(e.y))
使def on_selection(...
为class MultiListbox
的方法:
def on_selection(self, event):
# Get the current selected row
row = event.widget.curselection()[0]
# Clear previous selected row, select the current row
self.selection_clear(0, END)
self.selection_set(row)
# Create a dict record from all self.lists
# Use self.labels as dict key
record = {}
for column, lb in enumerate(self.lists):
record[self.labels[column]] = lb.get(row, row)[0]
print('Selection[{}]:{}'.format(row, record))
用法:
mlb = MultiListbox(leftbottomframe,
(('Location', 15),('RRD PN', 15),("Lot/Serial", 15),
('Description', 35), ('Customer PN', 15)))
for n in range(3):
mlb.insert(END, ['{}_{}'.format(label, n) for label in mlb.labels])
mlb.pack(expand=YES, fill=BOTH)
输出:
Selection[0]:{'Description': 'Description_0', 'Location': 'Location_0', 'Customer PN': 'Customer PN_0', 'Lot/Serial': 'Lot/Serial_0', 'RRD PN': 'RRD PN_0'} Selection[1]:{'Description': 'Description_1', 'Location': 'Location_1', 'Customer PN': 'Customer PN_1', 'Lot/Serial': 'Lot/Serial_1', 'RRD PN': 'RRD PN_1'} Selection[2]:{'Description': 'Description_2', 'Location': 'Location_2', 'Customer PN': 'Customer PN_2', 'Lot/Serial': 'Lot/Serial_2', 'RRD PN': 'RRD PN_2'}
使用Python测试:3.5