Python Tkinter GUI如何实现Listbox内年龄按从大到小排序
Tkinter用户信息录入程序年龄排序实现
问题背景
我编写了一个基于Python Tkinter的GUI程序,支持用户输入姓名、出生年份、出生月份、出生日期,选择性别,提交后各信息会分别写入对应Listbox控件展示,GUI运行效果如下:
当前程序存在问题:录入不同年龄的用户信息时,年龄列对应的Listbox不会自动将年龄值按照从大到小(年长到年幼)的顺序排序展示。
原有实现代码
from cmath import e from tkinter import* from datetime import date from tkinter import messagebox one = Tk() one.title("NICE") one.state("zoomed") today = date.today() clicked = StringVar() clicked.set("Male") def adi(): a.insert(END, three.get()) def gen(): if clicked.get() == "Male": b.insert(END, three.get()) else: c.insert(END, three.get()) def age(): d= int(birth_day.get()) m=int(birth_month.get()) y=int(birth_year.get()) age = today.year-y-((today.month, today.day)<(m,d)) d1.insert(END, age) two = [ "Male", "Female" ] frame = Frame(one) frame.pack(pady=5) lf = Frame(frame) lf.pack(pady=5) my_label = Label(lf, font=("Futura", 40),fg="#FFFFFF", text="Name") my_label.pack(side=LEFT, fill=BOTH, padx=120) a = Listbox(frame, font=("Futura", 25), width=20, height=6, bd=2, fg='#FFFFFF' ) a.pack(side=LEFT, fill=BOTH, padx=10) my_label = Label(lf, font=("Futura", 40),fg="#FFFFFF", text="Male") my_label.pack(side=LEFT, fill=BOTH, padx=120) b = Listbox(frame, font=("Futura", 25), width=20, height=6, bd=2, fg='#FFFFFF' ) b.pack(side=LEFT, fill=BOTH, padx=10) my_label = Label(lf, font=("Futura", 40),fg="#FFFFFF", text="Female") my_label.pack(side=LEFT, fill=BOTH, padx=120) c = Listbox(frame, font=("Futura", 25), width=20, height=6, bd=2, fg='#FFFFFF' ) c.pack(side=LEFT, fill=BOTH,padx=10) my_label = Label(lf, font=("Futura", 40),fg="#FFFFFF", text="Age") my_label.pack(side=LEFT, fill=BOTH, padx=120) d1 = Listbox(frame, font=("Futura", 25), width=20, height=6, bd=2, fg='#FFFFFF' ) d1.pack(side=LEFT, fill=BOTH, padx=10) frame2 = Frame(one) frame2.pack(pady=20) three = Entry(frame2, font=("Futura", 30)) three.pack(pady=20) age1 = Frame(frame2) age1.pack(pady=10) lbf = Frame(age1) lbf.pack() Label(lbf, text="Birth Year", font=("Futura", 30)).pack(pady=10, side=LEFT, padx=150) Label(lbf, text="Birth Month", font=("Futura", 30)).pack(pady=10, side=LEFT, padx=120) Label(lbf, text="Birth Date", font=("Futura", 30)).pack(pady=10, side=LEFT, padx=150) yearvalue = StringVar() monthvalue = StringVar() dayvalue = StringVar() birth_year = Entry(age1, textvariable=yearvalue, font=("Futura", 30)) birth_year.pack(pady=20, padx=20, side=LEFT) birth_month = Entry(age1, textvariable=monthvalue, font=("Futura", 30)) birth_month.pack(pady=20, padx=20, side=LEFT) birth_day = Entry(age1, textvariable=dayvalue, font=("Futura", 30)) birth_day.pack(pady=20, padx=20, side=LEFT) drop = OptionMenu(frame2, clicked, *two ).pack(pady=10) add = Button(frame2, text="Submit", command=lambda:[adi(), gen(), age()]).pack() one.mainloop()
实现逻辑
仅单独排序年龄Listbox会导致年龄、姓名、性别数据行错位,无法对应同一用户,因此需要统一管理所有用户数据,排序后同步刷新所有列表:
- 新增全局列表存储所有用户的完整数据,单条数据格式为
(年龄, 姓名, 性别) - 合并原分散的提交逻辑,提交时先校验输入合法性,计算用户年龄后存入全局列表
- 对全局列表按年龄降序(从大到小)排序
- 清空所有Listbox的旧内容,遍历排序后的数据,按顺序把对应字段写入各个Listbox,保证行数据一一对应
修改后可运行代码
from tkinter import * from datetime import date from tkinter import messagebox one = Tk() one.title("NICE") one.state("zoomed") today = date.today() # 存储所有用户数据的全局列表 user_list = [] clicked = StringVar() clicked.set("Male") def submit_info(): # 获取输入内容 name = three.get().strip() gender = clicked.get() # 输入合法性校验 if not name: messagebox.showerror("错误", "请输入姓名") return try: d = int(birth_day.get()) m = int(birth_month.get()) y = int(birth_year.get()) # 简单校验日期范围 if not (1900 <= y <= today.year and 1<=m<=12 and 1<=d<=31): raise ValueError except ValueError: messagebox.showerror("错误", "请输入合法的出生年月日数字") return # 计算年龄 age = today.year - y - ((today.month, today.day) < (m, d)) # 新增用户数据到列表 user_list.append((age, name, gender)) # 按年龄降序排序(从大到小) user_list.sort(reverse=True, key=lambda x: x[0]) # 清空所有列表原有内容 a.delete(0, END) b.delete(0, END) c.delete(0, END) d1.delete(0, END) # 遍历排序后的数据写入各个Listbox for user_age, user_name, user_gender in user_list: a.insert(END, user_name) if user_gender == "Male": b.insert(END, user_name) else: c.insert(END, user_name) d1.insert(END, user_age) # 清空输入框 three.delete(0, END) birth_year.delete(0, END) birth_month.delete(0, END) birth_day.delete(0, END) two = ["Male", "Female"] frame = Frame(one) frame.pack(pady=5) lf = Frame(frame) lf.pack(pady=5) my_label = Label(lf, font=("Futura", 40),fg="#FFFFFF", text="Name") my_label.pack(side=LEFT, fill=BOTH, padx=120) a = Listbox(frame, font=("Futura", 25), width=20, height=6, bd=2, fg='#FFFFFF' ) a.pack(side=LEFT, fill=BOTH, padx=10) my_label = Label(lf, font=("Futura", 40),fg="#FFFFFF", text="Male") my_label.pack(side=LEFT, fill=BOTH, padx=120) b = Listbox(frame, font=("Futura", 25), width=20, height=6, bd=2, fg='#FFFFFF' ) b.pack(side=LEFT, fill=BOTH, padx=10) my_label = Label(lf, font=("Futura", 40),fg="#FFFFFF", text="Female") my_label.pack(side=LEFT, fill=BOTH, padx=120) c = Listbox(frame, font=("Futura", 25), width=20, height=6, bd=2, fg='#FFFFFF' ) c.pack(side=LEFT, fill=BOTH,padx=10) my_label = Label(lf, font=("Futura", 40),fg="#FFFFFF", text="Age") my_label.pack(side=LEFT, fill=BOTH, padx=120) d1 = Listbox(frame, font=("Futura", 25), width=20, height=6, bd=2, fg='#FFFFFF' ) d1.pack(side=LEFT, fill=BOTH, padx=10) frame2 = Frame(one) frame2.pack(pady=20) three = Entry(frame2, font=("Futura", 30)) three.pack(pady=20) age1 = Frame(frame2) age1.pack(pady=10) lbf = Frame(age1) lbf.pack() Label(lbf, text="Birth Year", font=("Futura", 30)).pack(pady=10, side=LEFT, padx=150) Label(lbf, text="Birth Month", font=("Futura", 30)).pack(pady=10, side=LEFT, padx=120) Label(lbf, text="Birth Date", font=("Futura", 30)).pack(pady=10, side=LEFT, padx=150) yearvalue = StringVar() monthvalue = StringVar() dayvalue = StringVar() birth_year = Entry(age1, textvariable=yearvalue, font=("Futura", 30)) birth_year.pack(pady=20, padx=20, side=LEFT) birth_month = Entry(age1, textvariable=monthvalue, font=("Futura", 30)) birth_month.pack(pady=20, padx=20, side=LEFT) birth_day = Entry(age1, textvariable=dayvalue, font=("Futura", 30)) birth_day.pack(pady=20, padx=20, side=LEFT) drop = OptionMenu(frame2, clicked, *two ) drop.pack(pady=10) add = Button(frame2, text="Submit", command=submit_info) add.pack() one.mainloop()
额外优化点:新增了输入合法性校验,避免非数字输入导致程序崩溃;提交后自动清空输入框,方便下一次录入。
内容的提问来源于stack exchange,提问作者Wash-Basin
相关产品推荐
相关产品推荐

