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

Python tkinter/ctkinter无法从输入控件取值创建Student对象

问题:Tkinter/CustomTkinter无法获取控件输入值,创建Student实例失败

我用Tkinter和CustomTkinter开发学生信息录入GUI,想获取CTkEntry、DateEntry等控件的输入值来创建Student类实例,但点击「Create Student Record」按钮后,获取的不是输入值而是控件对象标识,导致Student对象无法正确填充数据。

Student类代码

class Student:
    def __init__(self, firstName=None, lastName=None, dateOfBirth=None, age=None, schoolName=None, schoolId=None, addressLine=None, city=None, zip=None, language=None):
        self.firstName = firstName
        self.lastName = lastName
        self.dateOfBirth = dateOfBirth
        self.age = age
        self.schoolName = schoolName
        self.schoolId = schoolId
        self.addressLine = addressLine
        self.city = city
        self.zip = zip
        self.language = language

原GUI代码

import sys
import tkinter
import customtkinter as ctk
import self
from tkcalendar import *
from datetime import date, datetime
from Student import *

# Theme set-up
ctk.set_appearance_mode("dark")
ctk.set_default_color_theme("dark-blue")

# GUI set-up
mainMenu = ctk.CTk()
mainMenu.title("GUI Application")
mainMenu.geometry("800x500")

# Frame set-up
mainMenuFrame = ctk.CTkFrame(master=mainMenu)
mainMenuFrame.pack(pady=20, padx=60, fill="both", expand=True)

ageSelection = tkinter.StringVar()

#Functions
def exitProgram():
    sys.exit()

def getAge(today, dob, student):
    print(today)
    print(dob)
    dob_result = str(dob)
    dob_data = dob_result.split("-")
    year = int(dob_data[0])
    month = int(dob_data[1])
    day = int(dob_data[2])

    print(year)
    print(month)
    print(day)

    age = (today - date(year, month, day)).days
    age = age / 365
    print(age)
    age = round(age)
    ageSelection = round(age)
    print(round(age))

def createStudentRecord(firstName, lastName, dob, schoolName, schoolId, addressLine, city, zip, language):
    s1 = Student(firstName, lastName,dob,schoolName,schoolId,addressLine, city, zip, language)
    print(firstName)
    print(lastName)
    print(dob)
    print(schoolId)
    print(addressLine)
    print(city)
    print(zip)
    print(language)

def loadStudentInfoView():
    # Remove main menu frame
    mainMenuFrame.pack_forget()

    studentInfoFrame = ctk.CTkFrame(master=mainMenu)
    studentInfoFrame.grid(row=0, column=0)

    # Student Info set-up

    #First & Last Name
    firstNameLabel = ctk.CTkLabel(master=studentInfoFrame, text="First Name", font=('Calibri',20))
    firstNameLabel.grid(row=0, column=0)

    firstNameText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=150)
    firstNameText.grid(row=1, column=0, padx=20)
    firstName = str(firstNameText.get())

    lastNameLabel = ctk.CTkLabel(master=studentInfoFrame, text="Last Name", font=('Calibri', 20))
    lastNameLabel.grid(row=0, column=1)

    lastNameText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=150)
    lastNameText.grid(row=1, column=1, padx=20)

    # Birth date (Calendar), automatically calculate age
    #DOB drop down

    dobLabel = ctk.CTkLabel(master=studentInfoFrame, text="DOB", font=('Calibri', 20))
    dobLabel.grid(row=0, column=2)

    calPicker = DateEntry(studentInfoFrame, selectmode="day", year=2014, month=2, day=7, date_pattern="yyyy-mm-dd")
    calPicker.grid(row=1, column=2)

    #School Details
    schoolNameLabel = ctk.CTkLabel(master=studentInfoFrame, text="School Name", font=('Calibri', 20))
    schoolNameLabel.grid(row=2, column=0)

    schoolNameText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=150)
    schoolNameText.grid(row=3, column=0, padx=20)

    #School ID
    schoolIdLabel = ctk.CTkLabel(master=studentInfoFrame, text="School ID", font=('Calibri', 20))
    schoolIdLabel.grid(row=2, column=1)

    schoolIdText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=70)
    schoolIdText.grid(row=3, column=1, padx=20)

    #Address Line 1 & 2, City, State, Zip
    addressLineLabel = ctk.CTkLabel(master=studentInfoFrame, text="Address Line", font=('Calibri', 20))
    addressLineLabel.grid(row=5, column=0)

    addressLineText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=300)
    addressLineText.grid(row=6, column=0, padx=20)

    cityLabel = ctk.CTkLabel(master=studentInfoFrame, text="City", font=('Calibri', 20))
    cityLabel.grid(row=5, column=1)

    cityText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=120)
    cityText.grid(row=6, column=1, padx=20)

    stateLabel = ctk.CTkLabel(master=studentInfoFrame, text="State (dropdown)", font=('Calibri', 20))
    stateLabel.grid(row=5, column=2)

    stateText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=50)
    stateText.grid(row=6, column=2, padx=20)

    zipLabel = ctk.CTkLabel(master=studentInfoFrame, text="Zip Code", font=('Calibri', 20))
    zipLabel.grid(row=5, column=3)

    zipText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=50)
    zipText.grid(row=6, column=3, padx=20)

    #Language

    # Create Record Button
    createRecordButton = ctk.CTkButton(master=studentInfoFrame, text="Create Student Record", command=lambda : createStudentRecord(firstName, lastNameText, calPicker, schoolNameText,
                                                                                                                          schoolIdText, addressLineText, cityText, zipText, language=None))
    createRecordButton.grid(row=8, column=1, pady=80)

# Main Menu Layout

# Title Label
title = ctk.CTkLabel(master = mainMenuFrame, text="LSSP Helper", font=('Arial', 32))
title.pack(pady=12, padx=10)

# Text Label
title2 = ctk.CTkLabel(master = mainMenuFrame, text="Can you")
title2.pack(pady=12, padx=10)

# Text Label
title3 = ctk.CTkLabel(master = mainMenuFrame, text="please")
title3.pack(pady=12, padx=10)

# Text Label
title4 = ctk.CTkLabel(master = mainMenuFrame, text="HELLLLLLLLLLLLLLLLLLLLLLLLLLLLLP!?!?!?!?!")
title4.pack(pady=12, padx=10)

# Button 1
button1 = ctk.CTkButton(master = mainMenuFrame, text="Create New Student Record", command=loadStudentInfoView)
button1.pack(pady=12, padx=10)

# Button 2
button2 = ctk.CTkButton(master = mainMenuFrame, text="Resume Student Record")
button2.pack(pady=12, padx=10)

# Button 3
button3 = ctk.CTkButton(master = mainMenuFrame, text="Observation Form")
button3.pack(pady=12, padx=10)

# Exit Button
exitButton = ctk.CTkButton(master = mainMenuFrame, text="Exit", command=exitProgram)
exitButton.pack(pady=12, padx=10)

mainMenu.mainloop()

原输出结果

# empty value as I tried to use text.get() method
.!ctkframe2.!ctkentry2
.!ctkframe2.!dateentry
.!ctkframe2.!ctkentry4
.!ctkframe2.!ctkentry5
.!ctkframe2.!ctkentry6
.!ctkframe2.!ctkentry8
None

问题原因

  1. 提前获取值导致空内容:初始化firstNameText后立即调用.get(),此时控件还没有用户输入,得到的是空值。
  2. 传递控件对象而非输入值:按钮命令中直接传递lastNameText、calPicker等控件对象,而非调用.get()获取当前输入值,打印时自然输出控件的身份标识。
  3. 参数顺序不匹配:createStudentRecord函数传递的参数顺序和Student类的__init__方法不匹配,导致数据填充错位。

修复方案

  1. 删除提前获取值的代码:移除firstName = str(firstNameText.get()),改为在按钮点击时获取值。
  2. 按钮点击时获取实时值:在按钮的command中,对每个输入控件调用.get()(DateEntry用.get_date()获取日期对象)。
  3. 修正参数顺序:确保传递给Student类的参数和__init__方法的参数顺序一致。
  4. 优化年龄计算:将年龄计算逻辑改为返回值形式,避免局部变量无法更新的问题。

修改后的完整GUI代码

import sys
import tkinter
import customtkinter as ctk
from tkcalendar import *
from datetime import date, datetime
from Student import *

# Theme set-up
ctk.set_appearance_mode("dark")
ctk.set_default_color_theme("dark-blue")

# GUI set-up
mainMenu = ctk.CTk()
mainMenu.title("GUI Application")
mainMenu.geometry("800x500")

# Frame set-up
mainMenuFrame = ctk.CTkFrame(master=mainMenu)
mainMenuFrame.pack(pady=20, padx=60, fill="both", expand=True)

#Functions
def exitProgram():
    sys.exit()

def calculateAge(dob):
    # 更准确的年龄计算方式
    today = date.today()
    age = today.year - dob.year - ((today.month, today.day) < (dob.month, dob.day))
    return age

def createStudentRecord(firstName, lastName, dob, schoolName, schoolId, addressLine, city, zip_code, language):
    age = calculateAge(dob)
    s1 = Student(firstName, lastName, dob, age, schoolName, schoolId, addressLine, city, zip_code, language)
    # 打印验证数据
    print("学生信息:")
    print(f"FirstName: {firstName}")
    print(f"LastName: {lastName}")
    print(f"DOB: {dob}")
    print(f"Age: {age}")
    print(f"SchoolName: {schoolName}")
    print(f"SchoolId: {schoolId}")
    print(f"AddressLine: {addressLine}")
    print(f"City: {city}")
    print(f"Zip: {zip_code}")
    print(f"Language: {language}")
    return s1

def loadStudentInfoView():
    # Remove main menu frame
    mainMenuFrame.pack_forget()

    studentInfoFrame = ctk.CTkFrame(master=mainMenu)
    studentInfoFrame.grid(row=0, column=0)

    #First & Last Name
    firstNameLabel = ctk.CTkLabel(master=studentInfoFrame, text="First Name", font=('Calibri',20))
    firstNameLabel.grid(row=0, column=0)

    firstNameText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=150)
    firstNameText.grid(row=1, column=0, padx=20)

    lastNameLabel = ctk.CTkLabel(master=studentInfoFrame, text="Last Name", font=('Calibri', 20))
    lastNameLabel.grid(row=0, column=1)

    lastNameText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=150)
    lastNameText.grid(row=1, column=1, padx=20)

    # Birth date (Calendar)
    dobLabel = ctk.CTkLabel(master=studentInfoFrame, text="DOB", font=('Calibri', 20))
    dobLabel.grid(row=0, column=2)

    calPicker = DateEntry(studentInfoFrame, selectmode="day", year=2014, month=2, day=7, date_pattern="yyyy-mm-dd")
    calPicker.grid(row=1, column=2)

    #School Details
    schoolNameLabel = ctk.CTkLabel(master=studentInfoFrame, text="School Name", font=('Calibri', 20))
    schoolNameLabel.grid(row=2, column=0)

    schoolNameText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=150)
    schoolNameText.grid(row=3, column=0, padx=20)

    #School ID
    schoolIdLabel = ctk.CTkLabel(master=studentInfoFrame, text="School ID", font=('Calibri', 20))
    schoolIdLabel.grid(row=2, column=1)

    schoolIdText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=70)
    schoolIdText.grid(row=3, column=1, padx=20)

    #Language
    languageLabel = ctk.CTkLabel(master=studentInfoFrame, text="Language", font=('Calibri', 20))
    languageLabel.grid(row=2, column=2)
    languageText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=100)
    languageText.grid(row=3, column=2, padx=20)

    #Address Line 1 & 2, City, State, Zip
    addressLineLabel = ctk.CTkLabel(master=studentInfoFrame, text="Address Line", font=('Calibri', 20))
    addressLineLabel.grid(row=5, column=0)

    addressLineText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=300)
    addressLineText.grid(row=6, column=0, padx=20)

    cityLabel = ctk.CTkLabel(master=studentInfoFrame, text="City", font=('Calibri', 20))
    cityLabel.grid(row=5, column=1)

    cityText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=120)
    cityText.grid(row=6, column=1, padx=20)

    stateLabel = ctk.CTkLabel(master=studentInfoFrame, text="State (dropdown)", font=('Calibri', 20))
    stateLabel.grid(row=5, column=2)

    stateText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=50)
    stateText.grid(row=6, column=2, padx=20)

    zipLabel = ctk.CTkLabel(master=studentInfoFrame, text="Zip Code", font=('Calibri', 20))
    zipLabel.grid(row=5, column=3)

    zipText = ctk.CTkEntry(master=studentInfoFrame, height=30, width=50)
    zipText.grid(row=6, column=3, padx=20)

    # Create Record Button
    createRecordButton = ctk.CTkButton(
        master=studentInfoFrame, 
        text="Create Student Record", 
        command=lambda : createStudentRecord(
            firstNameText.get(), 
            lastNameText.get(), 
            calPicker.get_date(), 
            schoolNameText.get(), 
            schoolIdText.get(), 
            addressLineText.get(), 
            cityText.get(), 
            zipText.get(), 
            languageText.get()
        )
    )
    createRecordButton.grid(row=8, column=1, pady=80)

# Main Menu Layout
title = ctk.CTkLabel(master = mainMenuFrame,
相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 03:31:53