前言:
原本我是不打算写下篇的,原因我也说了,没什么用纯粹是写着玩的,而且隔了好长时间了我也没什么印象了想要接上比较费时费力,但是我发现一件很神奇的事情,就是我觉得有用的文章没有太多人看,而这种花里胡哨的文章你们却很感兴趣,导致好多人问我要下篇,我想了想反正放假了也没什么事情,那就应广大网友的要求就把他补全吧(哈哈哈,想打我吗?)。
参考:Python GUI项目实战(一)登录窗体的设计与实现 – 云+社区 – 腾讯云 (tencent.com)
正文:
我们接着上一篇的内容继续做拓展,上篇我们实现了登录,显示,关键字搜索的操作,这一篇我们来把增删改查补全,再加上一个保存的功能。至此一个简单的学生信息管理系统就都搞定了。
老规矩先上图:
用户名和密码在最上方,可自行修改:
#先定义几个可能用到的常量user_name = "kkyyds" #凯子哥永远的神,哈哈password = "123456"
查询:
点击显示全部后,双击查看学生信息:
添加:
修改:
删除:
保存:
退出保存判定,若文件未作修改则不显示,刚保存过不显示,做出修改后未保存显示选择框:
明细窗体:
增加和修改我们需要一个新的窗口进行操作,为了提高代码的可读性,我们新开一个py文件,文件名就叫明细窗口。
from tkinter import *from tkinter.messagebox import showinfofrom tkinter.ttk import *class DetailWindow(Toplevel):def __init__(self):super().__init__()self.config(bg="#C9C9C9")self.title("学生明细信息")self.geometry("300x450+600+150")self.resizable(0,0) # 不能改变大小self.userinfo=0# 加载控件self.setup_UI()def setup_UI(self):# 加载一个paneself.Pane_detail = PanedWindow(self,width = 290,height = 430)self.Pane_detail.place(x = 10,y = 20)self.Style02 = Style(self.Pane_detail)#指定窗体,不指定则不显示样式self.Style02.configure("TPanedwindow", background="#C9C9C9")self.Style02.configure("detail.TLabel", font=("微软雅黑", 16, "bold"), background="#C9C9C9")self.Style02.configure("detail.TButton", font=("微软雅黑", 16, "bold"))self.Style02.configure("TEntry", font=("微软雅黑", 16, "bold"), width=10)self.Style02.configure("TRadiobutton", font=("微软雅黑", 16, "bold"), background="#C9C9C9")# 添加属性# 第一排:学号self.Label_sno = Label(self.Pane_detail,text = "学号:",style="detail.TLabel")self.Label_sno.place(x=10,y=10)self.var_sno = StringVar()self.Entry_sno = Entry(self.Pane_detail,textvariable = self.var_sno,font=("微软雅黑", 16,"bold"),width = 10)self.Entry_sno.place(x=80,y=8)# 专业:self.Label_pro = Label(self.Pane_detail, text="专业:",style="detail.TLabel")self.Label_pro.place(x=10, y=60)self.var_pro = StringVar()self.Entry_pro = Entry(self.Pane_detail, textvariable=self.var_pro, font=("微软雅黑", 16, "bold"), width=13)self.Entry_pro.place(x=80, y=58)# 班级self.Label_class = Label(self.Pane_detail, text="班级:",style="detail.TLabel")self.Label_class.place(x=10, y=110)self.var_class = StringVar()self.Entry_class = Entry(self.Pane_detail, textvariable=self.var_class, font=("微软雅黑", 16, "bold"), width=7)self.Entry_class.place(x=80, y=108)# 姓名self.Label_name = Label(self.Pane_detail, text="姓名:",style="detail.TLabel")self.Label_name.place(x=10, y=160)self.var_name = StringVar()self.Entry_name = Entry(self.Pane_detail, textvariable=self.var_name, font=("微软雅黑", 16, "bold"), width=7)self.Entry_name.place(x=80, y=158)# 性别self.Label_gender = Label(self.Pane_detail,text = "性别:",style="detail.TLabel").place(x=10,y = 210)self.var_gender = IntVar()self.Radio_man = Radiobutton(self.Pane_detail,text="男",variable = self.var_gender,value = 1)self.Radio_man.place(x=80,y = 210)self.Radio_woman = Radiobutton(self.Pane_detail, text="女", variable=self.var_gender, value=2)self.Radio_woman.place(x=130, y=210)# 绩点self.Label_jidian = Label(self.Pane_detail, text="绩点:",style="detail.TLabel")self.Label_jidian.place(x=10, y=260)self.var_jidian = StringVar()self.Entry_jidian = Entry(self.Pane_detail, textvariable=self.var_jidian, font=("微软雅黑", 16, "bold"), width=7)self.Entry_jidian.place(x=80, y=258)# 手机号码self.Label_mobile = Label(self.Pane_detail, text="手机号码:",style="detail.TLabel")self.Label_mobile.place(x=10, y=310)self.var_mobile = StringVar()self.Entry_mobile = Entry(self.Pane_detail, textvariable=self.var_mobile, font=("微软雅黑", 16, "bold"), width=11)self.Entry_mobile.place(x=120, y=308)# 放置按钮self.Button_save = Button(self, text="保存", style="detail.TButton",command=self.add_student_detail)self.Button_save02 = Button(self, text="保存", style="detail.TButton",command=self.update_student_detail)def show_save(self,all_student_list):self.Button_save.place(x=80, y=388)self.all_student_list=all_student_listdef tube(self,all_student_list):self.all_student_list=all_student_listdef load_student_detail(self,current_student_list,flag,index):if len(current_student_list) == 0:returnelse:self.var_sno.set(current_student_list[0])# 学号self.var_pro.set(current_student_list[1])self.var_class.set(current_student_list[2])self.var_name.set(current_student_list[3])if "男" in current_student_list[4]:self.var_gender.set(1)else:self.var_gender.set(2)self.var_jidian.set(current_student_list[5])self.var_mobile.set(current_student_list[6])if flag==1:# 控制控件的状态self.Button_save.place_forget()self.Entry_sno["state"] = DISABLEDself.Entry_name["state"] = DISABLEDself.Radio_man["state"] = DISABLEDself.Radio_woman["state"] = DISABLEDself.Entry_class["state"] = DISABLEDself.Entry_mobile["state"] = DISABLEDself.Entry_jidian["state"] = DISABLEDself.Entry_pro["state"] = DISABLEDelse:self.index = indexself.Button_save02.place(x=80, y=388)def add_student_detail(self):temp_list = []if len(str(self.Entry_sno.get()).strip()) == 0:showinfo("系统消息", "学号不能为空!")else:temp_list.append(str(self.Entry_sno.get()).strip())temp_list.append(str(self.Entry_pro.get()).strip())temp_list.append(str(self.Entry_class.get()).strip())temp_list.append(str(self.Entry_name.get()).strip())if self.var_gender.get() == 1:temp_list.append("男")else:temp_list.append("女")temp_list.append(str(self.Entry_jidian.get()).strip())temp_list.append(str(self.Entry_mobile.get()).strip())self.all_student_list.append(temp_list)self.userinfo=1# 提醒添加成功showinfo("系统消息", "学生信息添加成功")# 关闭窗体self.destroy()def update_student_detail(self):temp_list = []if len(str(self.Entry_sno.get()).strip()) == 0:showinfo("系统消息", "学号不能为空!")else:temp_list.append(str(self.Entry_sno.get()).strip())temp_list.append(str(self.Entry_pro.get()).strip())temp_list.append(str(self.Entry_class.get()).strip())temp_list.append(str(self.Entry_name.get()).strip())if self.var_gender.get() == 1:temp_list.append("男")else:temp_list.append("女")temp_list.append(str(self.Entry_jidian.get()).strip())temp_list.append(str(self.Entry_mobile.get()).strip())self.all_student_list[self.index]=temp_listself.userinfo = 1# 提醒添加成功showinfo("系统消息", "学生信息修改成功")# 关闭窗体self.destroy()if __name__ == '__main__':this_window = DetailWindow()this_window.mainloop()
主界面:
主界面要连接明细窗口,使用import导入明细窗口,在进行函数的书写。为了你们能够看的清晰直观,我就不进行代码的拆分了,直接全部放出,防止有的地方你们连接不上。
import tkinter as tkfrom tkinter import messageboxfrom tkinter.messagebox import showinfo, askyesnofrom tkinter.ttk import Style, PanedWindow, Button, LabelFrame, Treeviewimport pandas as pdfrom PIL import Image, ImageTkfrom tkinter import Frameimport timeimport 明细窗口#先定义几个可能用到的常量user_name = "kkyyds"password = "123456"LEFT = "left"RIGHT = "right"TOP = "top"BOTTOM = "bottom"Song = '宋体'Microsoft = '微软雅黑'class Root:# 这是第一个页面def __init__(self, window):self.window = windowself.window.title("教学管理系统")self.window.geometry("1000x600+250+100")self.window.resizable(0,0) # 窗体大小不允许变,两个参数分别代表x轴和y轴self.frame = Frame(self.window)self.frame.config(bg="#C9C9C9")self.frame.pack()self.img_lable()self.lable()self.clock()self.login()def lable(self):tk.Label(self.frame, text="新版教学管理系统", font=(Song, 20), bg="#C9C9C9").place(relx=0.73, rely=0.45, relheight=0.05, relwidth=0.25)tk.Label(self.frame, text="清华大学", font=("楷体", 30), bg="#C9C9C9").place(relx=0.73, rely=0.35, relheight=0.08, relwidth=0.25)tk.Label(self.frame, text="作者: CSDN@星空的你", font=("楷体", 10), bg="#C9C9C9").place(relx=0.73, rely=0.85,relheight=0.08, relwidth=0.25)def img_lable(self):# photo1=tk.PhotoImage(file = '大学.png')#仅支持png和gifimg2 = Image.open("大学.jpg")img1 = Image.open("清华大学.png")img2 = img2.resize((700, 600))# 规定图片大小img1 = img1.resize((300, 200))# 规定图片大小photo2 = ImageTk.PhotoImage(img2)# 使用神器PIL库可以设置照片大小并且可以支持jpg格式等photo1 = ImageTk.PhotoImage(img1)# 使用神器PIL库可以设置照片大小并且可以支持jpg格式等label2 = tk.Label(self.frame, image=photo2, borderwidth=0)label1 = tk.Label(self.frame, image=photo1, borderwidth=0)label2.img = photo2# to keep the reference for the image.不保存会显示空白label1.img = photo1# to keep the reference for the image.不保存会显示空白label2.grid(row=0, column=0)label1.grid(row=0, column=1, sticky="n")#n就是北North表示最上方def login(self):# 将俩个标签分别布置在第一行、第二行tk.Label(self.frame, text="账号:", font=(Song, 15), bg="#C9C9C9").place(relx=0.7, rely=0.55, relheight=0.04,relwidth=0.1)tk.Label(self.frame, text="密码:", font=(Song, 15), bg="#C9C9C9").place(relx=0.7, rely=0.62, relheight=0.04,relwidth=0.1)# 创建输入框控件self.e1 = tk.Entry(self.frame)# 以 * 的形式显示密码self.e2 = tk.Entry(self.frame, show='*')self.e1.place(relx=0.8, rely=0.55, relheight=0.04, relwidth=0.18)self.e2.place(relx=0.8, rely=0.62, relheight=0.04, relwidth=0.18)tk.Button(self.frame, text="登录", width=20, command=self.check).place(relx=0.7, rely=0.7, relheight=0.06, relwidth=0.1)tk.Button(self.frame, text="退出", width=20, command=self.window.quit).place(relx=0.9, rely=0.7, relheight=0.06, relwidth=0.1)def check(self):if self.e1.get() == user_name and self.e2.get() == password:messagebox.showinfo(title="登陆成功", message=f"欢迎回来,{user_name}!")self.frame.destroy()Home(self.window)return Trueelse:messagebox.showwarning(title="登录失败", message="账号或密码错误")self.e2.delete(0, tk.END)return Falsedef clock(self):# 获取时间的函数def gettime():# 获取当前时间dstr.set(time.strftime("%H:%M:%S"))# 每隔 1s 调用一次 gettime()函数来获取时间self.frame.after(1000, gettime)# 生成动态字符串dstr = tk.StringVar()# 利用 textvariable 来实现文本变化tk.Label(self.frame, textvariable=dstr, fg='green', font=("微软雅黑", 10), bg="#C9C9C9").place(relx=0.9, rely=0.93, relheight=0.08, relwidth=0.1)tk.Label(self.frame, text="time:", fg='green', font=("微软雅黑", 10), bg="#C9C9C9").place(relx=0.875, rely=0.93,relheight=0.08,relwidth=0.05)# 调用生成时间的函数gettime()action_flag=1class Home():def __init__(self, window):self.window = windowself.window.title(f"当前管理员为{user_name}")self.setup_UI()self.readExcel()self.query_result_list = []self.flag = action_flagself.update=0self.window.protocol("WM_DELETE_WINDOW", self.close_window)def readExcel(self):self.head=pd.read_excel("学生信息.xlsx").columns.tolist()df = pd.read_excel("学生信息.xlsx",usecols="A:G",dtype=str)self.all_student_list = df.values.tolist()#把每一行存入一个列表再把每个列表存入列表def del_Entry_content(self):self.Entry_sno.delete(0, tk.END)self.Entry_name.delete(0, tk.END)self.Entry_profess.delete(0, tk.END)self.Entry_class.delete(0, tk.END)def show_all(self):self.clear_Tree()# 把所有条件文本框清空self.Entry_sno.delete(0, tk.END)self.Entry_name.delete(0, tk.END)self.Entry_profess.delete(0, tk.END)self.Entry_class.delete(0, tk.END)self.load_treeview(self.all_student_list)def load_treeview(self,current_list):for index in range(len(current_list)):self.Tree.insert("", index, values=(current_list[index][0],current_list[index][1],current_list[index][2],current_list[index][3],current_list[index][4],current_list[index][5],current_list[index][6]))def get_query_result(self):query_condition = []query_condition.append(self.Entry_sno.get().strip())# 采集学号信息query_condition.append(self.Entry_name.get().strip())# 采集姓名信息query_condition.append(self.Entry_profess.get().strip())query_condition.append(self.Entry_class.get().strip())# 遍历List获取符合条件的学生信息for item in self.all_student_list:if query_condition[0] in item[0] and query_condition[1] in item[3] and \query_condition[2] in item[1] and query_condition[3] in item[2]:# 满足条件的学生self.query_result_list.append(item)# 把结果加载的TreeView中self.clear_Tree()self.load_treeview(self.query_result_list)self.query_result_list.clear()def clear_Tree(self):for i in self.Tree.get_children():self.Tree.delete(i)def setup_UI(self):# 设定Styleself.Style01 = Style()self.Style01.configure("TPanedwindow", background="#C9C9C9")self.Style01.configure("TButton", width=10, font=(Song, 15,))# 上边:labeself.Pane_top = PanedWindow(self.window,width=980, height=85, style="TPanedwindow").place(x=10, y=5)tk.Label(self.Pane_top, text="学生信息管理系统", bg='#C9C9C9', font=("微软雅黑", 40), width=30).place(x=15, y=10)# 左边:按钮区域,创建一个容器self.Pane_left = PanedWindow(self.window,width=195, height=500, style="TPanedwindow").place(x=10, y=95)# 这种写法下方是使用绝对距离self.Pane_right = PanedWindow(self.window,width=780, height=500, style="TPanedwindow")self.Pane_right.place(x=210, y=95)# 这种写法下方是相对距离,明明写法含义都一样,结果却不一样简直莫名其妙。。。不是frame的原因,因为你把它挪上去在结尾添加下方frame位置会改变# 添加左边按钮self.Button_add = Button(self.Pane_left, text="添加学生", style="TButton",command=self.add_student).place(x=50, y=120)self.Button_update = Button(self.Pane_left, text="修改学生", style="TButton",command=self.update_student).place(x=50, y=160)self.Button_delete = Button(self.Pane_left, text="删除学生", style="TButton",command=self.delete_student).place(x=50, y=200)self.Button_modify = Button(self.Pane_left, text="保存文件", style="TButton",command=self.save_excel).place(x=50, y=260)# 添加右边按钮# LabelFrameself.LabelFrame_query = LabelFrame(self.Pane_right, text="学生信息查询", width=770, height=40)self.LabelFrame_query.place(x=5, y=5)# 添加控件y1 = 1y2 = -2self.Label_sno = tk.Label(self.LabelFrame_query, text="学号:")self.Label_sno.place(x=5, y=y1)self.Entry_sno = tk.Entry(self.LabelFrame_query, width=12)self.Entry_sno.place(x=40, y=y2)self.Label_name = tk.Label(self.LabelFrame_query, text="姓名:")self.Label_name.place(x=125, y=y1)self.Entry_name = tk.Entry(self.LabelFrame_query, width=12)self.Entry_name.place(x=160, y=y2)self.Label_profess = tk.Label(self.LabelFrame_query, text="专业:")self.Label_profess.place(x=245, y=y1)self.Entry_profess = tk.Entry(self.LabelFrame_query, width=14)self.Entry_profess.place(x=280, y=y2)self.Label_class = tk.Label(self.LabelFrame_query, text="班级:")self.Label_class.place(x=380, y=y1)self.Entry_class = tk.Entry(self.LabelFrame_query, width=14)self.Entry_class.place(x=415, y=y2)self.Button_query = tk.Button(self.LabelFrame_query, text="查询", width=4,command=self.get_query_result)self.Button_query.place(x=520, y=y1 - 9)self.Button_query = tk.Button(self.LabelFrame_query, text="清除", width=4, command=self.del_Entry_content)self.Button_query.place(x=560, y=y1 - 9)self.Button_all = tk.Button(self.LabelFrame_query, text="清空全部", width=8, command=self.clear_Tree)self.Button_all.place(x=630, y=y2 - 8)self.Button_all = tk.Button(self.LabelFrame_query, text="显示全部", width=8,command=self.show_all)self.Button_all.place(x=700, y=y2 - 8)# 添加TreeView控件self.Tree = Treeview(self.Pane_right, columns=("sno", "专业", "班级", "names", "gender", "绩点", "mobile"), show="headings", height=21)# 设置每一个列的宽度和对齐的方式self.Tree.column("sno", width=120, anchor="center")self.Tree.column("names", width=100, anchor="center")self.Tree.column("gender", width=70, anchor="center")self.Tree.column("mobile", width=125, anchor="center")self.Tree.column("专业", width=140, anchor="center")self.Tree.column("班级", width=140, anchor="center")self.Tree.column("绩点", width=70, anchor="center")# 设置每个列的标题self.Tree.heading("sno", text="学号")self.Tree.heading("names", text="姓名")self.Tree.heading("gender", text="性别")self.Tree.heading("mobile", text="手机号码")self.Tree.heading("专业", text="专业")self.Tree.heading("班级", text="班级")self.Tree.heading("绩点", text="绩点")self.Tree.place(x=5, y=50)self.Tree.bind("", self.view_student)def show_window(self):self.detail_window = 明细窗口.DetailWindow()def add_student(self):self.show_window()self.detail_window.show_save(self.all_student_list)self.window.wait_window(self.detail_window)#等待窗口被销毁if self.detail_window.userinfo == 1:self.show_all()self.update=1else:returndef view_student(self,event):#此处event不可省略,删除后果自负# 获取Tree表格双击某一行的数据,selection()如果没有指定参数,则表明以列表形式返回所有的itemitem = self.Tree.selection()[0]# 获取双击某一行的项目标识符#一行数据所组成的列表current_student_list = self.Tree.item(item, "values")self.show_window()self.detail_window.load_student_detail(current_student_list,1,-1)def update_student(self):try:item = self.Tree.selection()[0]# 获取双击某一行的项目标识符except:showinfo("系统消息", "请选择要修改的学生")return# 一行数据所组成的列表current_student_list = self.Tree.item(item, "values")# 遍历获得完整学生明细信息index=self.all_student_list.index(list(current_student_list))self.show_window()self.detail_window.tube(self.all_student_list)self.detail_window.load_student_detail(current_student_list,2,index)self.window.wait_window(self.detail_window)#等待窗口被销毁if self.detail_window.userinfo == 1:self.show_all()self.update=1else:returndef delete_student(self):try:item = self.Tree.selection()[0]# 获取双击某一行的项目标识符except:showinfo("系统消息", "请选择要删除的学生")return# 一行数据所组成的列表current_student_list = self.Tree.item(item, "values")# 遍历获得完整学生明细信息index=self.all_student_list.index(list(current_student_list))# 询问是否删除choose = askyesno("删除确认", "确定要删除该学生【学号:" + current_student_list[0] + ",姓名:" +current_student_list[3] + "】的信息吗?")if choose:# 执行删除动作del self.all_student_list[index]self.show_all()showinfo("系统消息", "删除成功!")self.update=1else:returndef save_excel(self):if (self.update == 0):showinfo("系统消息", "当前文件未作修改,无需保存")returntry:dic = {}for i in range(0, len(self.head)):lst = []for student in self.all_student_list:lst.append(student[i])dic[self.head[i]] = lstdf = pd.DataFrame(dic)df.to_excel("学生信息.xlsx", index=False)# 提醒showinfo("系统消息", "保存成功")self.update=0except:showinfo("系统消息", "写入文件出现异常")def close_window(self):if(self.update==0):self.window.destroy()return# 给用户提示:是否要保存数据choose = askyesno("关闭前提醒", "关闭窗体前是否要将修改写入文件")if choose:try:dic = {}for i in range(0, len(self.head)):lst = []for student in self.all_student_list:lst.append(student[i])dic[self.head[i]] = lstdf = pd.DataFrame(dic)df.to_excel("学生信息.xlsx", index=False)# 提醒showinfo("系统消息", "所有的修改已经写入到文件")# 关闭self.window.destroy()except:showinfo("系统消息", "写入文件出现异常")else:self.window.destroy()if __name__ == '__main__':root = tk.Tk()Root(root)root.mainloop()
需要项目文件吗?
tkinter版教务系统-Python文档类资源-CSDN文库
如果收费了,记得跟我说,我把它调回来。
这么善良的作者值得你的点赞和收藏吗?