在本教程中,我们将实现一个有吸引力且用户友好的桌面应用程序学生管理系统。此应用程序用于存储学生的数据。我们可以将此应用程序用作我们学院的一个小项目。这个应用程序基本上是使用 python 框架 Tkinter 实现的,它提供了实现桌面应用程序的工具。
主要创建了 2 个框架,一个框架存储数据,另一个框架用于显示数据。
存储每个学生的一些信息,如学号、姓名、父亲姓名、学历、专业、联系电话和地址。
4个功能来添加数据
、更新数据
、删除数据
和清除数据
。并且所有字段都是必需的,如果数据存在于数据库中则删除数据,如果数据从数据库中获取并且在数据库中可用则更新数据。
还可以快速选中一条数据然后修改进行新增
创建表code
# SQ.py
import sqlite3
from sqlite3 import Error
def create_connection(db_file):
""" create a database connection to the SQLite database
specified by db_file
:param db_file: database file
:return: Connection object or None
"""
conn = None
try:
conn = sqlite3.connect(db_file)
return conn
except Error as e:
print(e)
return conn
def create_table(conn, create_table_sql):
""" create a table from the create_table_sql statement
:param conn: Connection object
:param create_table_sql: a CREATE TABLE statement
:return:
"""
try:
c = conn.cursor()
c.execute(create_table_sql)
except Error as e:
print(e)
def main():
database = r"SQLite_Python.db"
sql_create_projects_table = """CREATE TABLE IF NOT EXISTS students (
Roll_no varchar(15) PRIMARY KEY,
Name varchar(30) NOT NULL,
Father_Name varchar(55) NOT NULL,
Gender varchar(10) NOT NULL,
Category varchar(10) NOT NULL,
Branch varchar(30) NOT NULL,
Year varchar(10) NOT NULL,
Contact_no varchar(10) NOT NULL,
Address varchar(200) NOT NULL
);"""
# create a database connection
conn = create_connection(database)
# create tables
if conn is not None:
# create projects table
create_table(conn, sql_create_projects_table)
else:
print("Error! cannot create the database connection.")
if __name__ == '__main__':
main()
主程序code
# Student.py
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
import sqlite3
# from icecream import ic
class Student:
width = 1550
height = 800
def __init__(self, root):
self.root = root
self.root.title("学生信息管理系统")
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
x = int(screen_width / 2 - Student.width / 2)
y = int(screen_height / 2 - Student.height / 2)
self.root.geometry(f"{Student.width}x{Student.height}+{x}+{y}")
self.root.resizable(False, False)
self.roll_no = StringVar()
self.name = StringVar()
self.father_name = StringVar()
self.gen = StringVar()
self.category = StringVar()
self.branch = StringVar()
self.year = StringVar()
self.contact = StringVar()
self.search_by = StringVar()
self.search_txt = StringVar()
self.totalrecord = StringVar()
headinglbl = Label(root, text="Student Management System", font=("arial", 24, "bold"), bg='#7F7FFF', fg='red')
headinglbl.pack(side=TOP, fill=X)
# ***********Frame-1***************
entry_frame = Frame(root, bd=5, relief='ridge', bg='#E0E0EE')
entry_frame.place(x=20, y=50, width=350, height=745)
# Labels of frame-1
reg_lbl = Label(entry_frame, text="注册表单", font=("arial", 20, "bold"), bg='#E0E0EE', fg='red')
reg_lbl.grid(row=0, columnspan=2)
roll_lbl = Label(entry_frame, text="学号", font=("Heiti TC", 13), bg='#E0E0EE')
roll_lbl.grid(row=1, column=0, sticky='w', padx=10, pady=11)
name_lbl = Label(entry_frame, text="姓名", font=("Heiti TC", 13), bg='#E0E0EE')
name_lbl.grid(row=2, column=0, sticky='w', padx=10, pady=11)
Fname_lbl = Label(entry_frame, text="父亲名字", font=("Heiti TC", 13), bg='#E0E0EE')
Fname_lbl.grid(row=3, column=0, sticky='w', padx=10, pady=11)
gen_lbl = Label(entry_frame, text="姓别", font=("Heiti TC", 13), bg='#E0E0EE')
gen_lbl.grid(row=4, column=0, sticky='w', padx=10, pady=11)
cat_lbl = Label(entry_frame, text="学历", font=("Heiti TC", 13), bg='#E0E0EE')
cat_lbl.grid(row=5, column=0, sticky='w', padx=10, pady=11)
branch_lbl = Label(entry_frame, text="专业", font=("Heiti TC", 13), bg='#E0E0EE')
branch_lbl.grid(row=6, column=0, sticky='w', padx=10, pady=11)
yr_lbl = Label(entry_frame, text="学年制", font=("Heiti TC", 13), bg='#E0E0EE')
yr_lbl.grid(row=7, column=0, sticky='w', padx=10, pady=11)
phn_lbl = Label(entry_frame, text="联系方式", font=("Heiti TC", 13), bg='#E0E0EE')
phn_lbl.grid(row=8, column=0, sticky='w', padx=10, pady=11)
add_lbl = Label(entry_frame, text="家庭地址", font=("Heiti TC", 15), bg='#E0E0EE')
add_lbl.grid(row=9, column=0, sticky='w', padx=10, pady=11)
# Entry box of Frame-1
roll_entry = Entry(entry_frame, width=29, bd=3, bg='#E0E0EE', relief='ridge', font=("STSong", 12), textvariable=self.roll_no)
roll_entry.grid(row=1, column=1, sticky='w', padx=10, pady=11)
name_entry = Entry(entry_frame, width=29, bd=3, bg='#E0E0EE', relief='ridge', font=("STSong", 12), textvariable=self.name)
name_entry.grid(row=2, column=1, sticky='w', padx=10, pady=11)
fname_entry = Entry(entry_frame, width=29, bd=3, bg='#E0E0EE', relief='ridge', font=("STSong", 12), textvariable=self.father_name)
fname_entry.grid(row=3, column=1, sticky='w', padx=10, pady=11)
gen_combo = ttk.Combobox(entry_frame, state='readonly', width=18, textvariable=self.gen)
gen_combo['values'] = ('男', '女')
gen_combo.current(0)
gen_combo.grid(row=4, column=1, sticky='w', padx=10, pady=11)
cat_combo = ttk.Combobox(entry_frame, state='readonly', width=18, textvariable=self.category)
cat_combo['values'] = ('本科', '大专', '中专', '高中')
cat_combo.current(0)
cat_combo.grid(row=5, column=1, sticky='w', padx=10, pady=11)
branch_combo = ttk.Combobox(entry_frame, state='readonly', width=18, textvariable=self.branch)
branch_combo['values'] = ('哲学','经济学','法学','教育学','文学','历史学','理学','工学','农学','医学','管理学','艺术学')
branch_combo.current(0)
branch_combo.grid(row=6, column=1, sticky='w', padx=10, pady=11)
yr_combo = ttk.Combobox(entry_frame, state='readonly', width=18, textvariable=self.year)
yr_combo['values'] = ('4年', '3年', '2年', '1年')
yr_combo.current(0)
yr_combo.grid(row=7, column=1, sticky='w', padx=10, pady=11)
phn_entry = Entry(entry_frame, width=29, bd=3, bg='#E0E0EE', relief='ridge', font=("STSong", 12), textvariable=self.contact)
phn_entry.grid(row=8, column=1, sticky='w', padx=10, pady=11)
self.add_txt = Text(entry_frame, width=29, height=5, font=("Times", 12))
self.add_txt.grid(row=9, column=1, sticky='w', padx=10, pady=11)
# ***************Functions*********************
def add_data():
con = sqlite3.connect('SQLite_Python.db')
cur = con.cursor()
# ic(str(self.roll_no.get()))
cur.execute("select * from students where Roll_no=?", (str(self.roll_no.get()), ))
rows = cur.fetchall()
if len(rows) != 0:
messagebox.showerror('Error', f'学号:{str(self.roll_no.get())} 的学生信息已存在!')
else:
if self.roll_no.get() == "" or self.name.get() == "" or self.father_name.get() == "" or self.contact.get() == "" or self.add_txt.get(
'1.0', END) == "" or len(self.contact.get()) != 11:
messagebox.showerror('Error', '所有字段都不能为空且联系方式必须长度11位')
else:
info = str(self.roll_no.get())
cur.execute("""insert into students values(?,?,?,?,?,?,?,?,?)""", (
self.roll_no.get(), self.name.get(), self.father_name.get(), self.gen.get(), self.category.get(),
self.branch.get(), self.year.get(), self.contact.get(), self.add_txt.get('1.0', END)))
con.commit()
con.close()
fetch_data()
clear_data()
messagebox.showinfo('Success', f'{info} 添加成功!')
def fetch_data():
con = sqlite3.connect('SQLite_Python.db')
cur = con.cursor()
cur.execute('select * from students')
rows = cur.fetchall()
if rows != 0:
self.totalrecord.set(len(rows))
table.delete(*table.get_children())
for row in rows:
table.insert('', END, values=row)
con.commit()
con.close()
def clear_data():
self.roll_no.set("")
self.name.set("")
self.father_name.set("")
self.gen.set("")
self.category.set("")
self.branch.set("")
self.year.set("")
self.contact.set("")
self.add_txt.delete('1.0', END)
def focus(e):
cursor = table.focus()
content = table.item(cursor)
row = content['values']
self.roll_no.set(row[0])
self.name.set(row[1])
self.father_name.set(row[2])
self.gen.set(row[3])
self.category.set(row[4])
self.branch.set(row[5])
self.year.set(row[6])
self.contact.set(row[7])
self.add_txt.delete('1.0', END)
self.add_txt.insert(END, row[8])
def update_data():
if self.roll_no.get() == "" or self.name.get() == "" or self.father_name.get() == "" or self.contact.get() == "" or self.add_txt.get(
'1.0', END) == "" or len(self.contact.get()) != 11:
messagebox.showerror('Error', '必须填写所有字段')
else:
info = self.roll_no.get()
con = sqlite3.connect('SQLite_Python.db')
cur = con.cursor()
cur.execute(
'update students set Name=? , Father_Name=? , Gender=? , Category=? , Branch=? , Year=? , Contact_no=? , Address=? where Roll_no=? ',
(self.name.get(), self.father_name.get(), self.gen.get(), self.category.get(), self.branch.get(),
self.year.get(), self.contact.get(), self.add_txt.get('1.0', END), self.roll_no.get()))
con.commit()
con.close()
fetch_data()
clear_data()
messagebox.showinfo('Success', f'{info} 更新成功')
def delete_data():
if self.roll_no.get():
info = self.roll_no.get()
con = sqlite3.connect('SQLite_Python.db')
cur = con.cursor()
cur.execute('delete from students where Roll_no=?', (info,))
con.commit()
con.close()
fetch_data()
clear_data()
messagebox.showinfo('Success', f'{info}已被删除成功')
else:
messagebox.showinfo('Warning', f'未选中任何数据')
def search():
con = sqlite3.connect('SQLite_Python.db')
cur = con.cursor()
if str(self.search_by.get()) == "学号":
search = 'Roll_no'
else:
search = 'Contact_no'
cur.execute("select * from students where " + search + " LIKE '%" + str(
self.search_txt.get()) + "%'")
rows = cur.fetchall()
if len(rows) != 0:
table.delete(*table.get_children())
for row in rows:
table.insert('', END, values=row)
con.commit()
else:
messagebox.showinfo('Not found', 'Record not found')
con.close()
# **********Frame-3 Button**************
btn_frame = Frame(entry_frame, bd=5, relief='ridge', bg='#E0E0EE')
btn_frame.place(x=15, y=590, width=310, height=120)
add_btn = Button(btn_frame, text='Add', font=("", 12), command=add_data, width="7", bg='#E0E0EE')
add_btn.grid(row=0, column=1, padx=50, pady=10)
update_btn = Button(btn_frame, text='Update', font=("", 12), command=update_data, width="7", bg='#E0E0EE')
update_btn.grid(row=0, column=2, padx=10, pady=10)
delete_btn = Button(btn_frame, text='Delete', font=("", 12), command=delete_data, width="7", bg='#E0E0EE')
delete_btn.grid(row=1, column=1, padx=50, pady=10)
clear_btn = Button(btn_frame, text='Clear', font=("", 12), command=clear_data, width="7", bg='#E0E0EE')
clear_btn.grid(row=1, column=2, padx=10, pady=10)
# ***********Frame-2***************
data_frame = Frame(root, bd=5, relief='ridge', bg='#E0E0EE')
data_frame.place(x=380, y=50, width=1145, height=745)
# ***********Frame-2 code*****************
search_lbl = Label(data_frame, text="Search by", font=("", 13), bg='#E0E0EE')
search_lbl.grid(row=0, column=0, sticky='w', padx=10, pady=14)
search_combo = ttk.Combobox(data_frame, state='readonly', textvariable=self.search_by)
search_combo['values'] = ('学号', '联系方式')
search_combo.current(0)
search_combo.grid(row=0, column=1, sticky='w', padx=10, pady=14)
search_entry = Entry(data_frame, bd=3, relief='ridge', font=("", 12), width=15, textvariable=self.search_txt)
search_entry.grid(row=0, column=2, sticky='w', padx=10, pady=14)
show_btn = Button(data_frame, text='查找', font=("", 12), command=search)
show_btn.grid(row=0, column=3, padx=10, pady=10)
showall_btn = Button(data_frame, text='查找所有', font=("", 12), command=fetch_data)
showall_btn.grid(row=0, column=4, padx=10, pady=10)
total_lbl = Label(data_frame, text="Total Records", font=("", 13), bg='#E0E0EE')
total_lbl.grid(row=1, column=0, sticky='w', padx=10, pady=8)
totalrecord_lbl = Label(data_frame, text="Total Records", font=("", 13), textvariable=self.totalrecord)
totalrecord_lbl.grid(row=1, column=1, sticky='w', padx=10, pady=8)
# ************Frame-3 Treeview***************
view_frame = Frame(data_frame, bd=5, relief='ridge', bg='wheat')
view_frame.place(x=20, y=100, width=1080, height=620)
x_scroll = Scrollbar(view_frame, orient=HORIZONTAL)
y_scroll = Scrollbar(view_frame, orient=VERTICAL)
table=ttk.Treeview(view_frame,columns=('Roll_no.','Name','Father_Name','Gender','Category','Branch','Year','Contact_no.','Address'),xscrollcommand=x_scroll.set,yscrollcommand=y_scroll.set)
x_scroll.pack(side=BOTTOM, fill=X)
y_scroll.pack(side=RIGHT, fill=Y)
x_scroll.configure(command=table.xview)
y_scroll.configure(command=table.yview)
table.heading("Roll_no.", text="学号")
table.heading("Name", text="姓名")
table.heading("Father_Name", text="父亲名字")
table.heading("Gender", text="姓别")
table.heading("Category", text="学历")
table.heading("Branch", text="专业")
table.heading("Year", text="学年制")
table.heading("Contact_no.", text="联系方式")
table.heading("Address", text="家庭住址")
table.column("Roll_no.", width=100)
table.column("Name", width=100)
table.column("Father_Name", width=100)
table.column("Gender", width=100)
table.column("Category", width=100)
table.column("Branch", width=100)
table.column("Year", width=100)
table.column("Contact_no.", width=100)
table.column("Address", width=100)
table['show'] = 'headings'
table.bind('' , focus)
fetch_data()
table.pack(fill=BOTH, expand=1)
root = Tk()
ob = Student(root)
root.mainloop()
SQ.py
和 Student.py
放置同一文件夹下SQ.py
创建数据表。Student.py
即可