You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Tkinter GUI如何实现Listbox内年龄按从大到小排序

Tkinter用户信息录入程序年龄排序实现

问题背景

我编写了一个基于Python Tkinter的GUI程序,支持用户输入姓名、出生年份、出生月份、出生日期,选择性别,提交后各信息会分别写入对应Listbox控件展示,GUI运行效果如下:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 15:00:53