原本我是不打算写下篇的,原因我也说了,没什么用纯粹是写着玩的,而且隔了好长时间了我也没什么印象了想要接上比较费时费力,但是我发现一件很神奇的事情,就是我觉得有用的文章没有太多人看,而这种花里胡哨的文章你们却很感兴趣,导致好多人问我要下篇,我想了想反正放假了也没什么事情,那就应广大网友的要求就把他补全吧(哈哈哈,想打我吗?)。
参考:Python GUI项目实战(一)登录窗体的设计与实现 - 云+社区 - 腾讯云 (tencent.com)
我们接着上一篇的内容继续做拓展,上篇我们实现了登录,显示,关键字搜索的操作,这一篇我们来把增删改查补全,再加上一个保存的功能。至此一个简单的学生信息管理系统就都搞定了。
老规矩先上图:
用户名和密码在最上方,可自行修改:
#先定义几个可能用到的常量 user_name = "kkyyds" #凯子哥永远的神,哈哈 password = "123456"
查询:
点击显示全部后,双击查看学生信息:
添加:
修改:
删除:
保存:
退出保存判定,若文件未作修改则不显示,刚保存过不显示,做出修改后未保存显示选择框:
增加和修改我们需要一个新的窗口进行操作,为了提高代码的可读性,我们新开一个py文件,文件名就叫明细窗口。
- from tkinter import *
- from tkinter.messagebox import showinfo
- from 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):
-
-
- # 加载一个pane
- self.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_list
- def tube(self,all_student_list):
- self.all_student_list=all_student_list
- def load_student_detail(self,current_student_list,flag,index):
-
- if len(current_student_list) == 0:
- return
- else:
- 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"] = DISABLED
- self.Entry_name["state"] = DISABLED
- self.Radio_man["state"] = DISABLED
- self.Radio_woman["state"] = DISABLED
- self.Entry_class["state"] = DISABLED
- self.Entry_mobile["state"] = DISABLED
- self.Entry_jidian["state"] = DISABLED
- self.Entry_pro["state"] = DISABLED
- else:
- self.index = index
- self.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_list
- self.userinfo = 1
- # 提醒添加成功
- showinfo("系统消息", "学生信息修改成功")
- # 关闭窗体
- self.destroy()
-
-
-
-
-
-
- if __name__ == '__main__':
- this_window = DetailWindow()
- this_window.mainloop()
主界面要连接明细窗口,使用import导入明细窗口,在进行函数的书写。为了你们能够看的清晰直观,我就不进行代码的拆分了,直接全部放出,防止有的地方你们连接不上。
- import tkinter as tk
- from tkinter import messagebox
- from tkinter.messagebox import showinfo, askyesno
- from tkinter.ttk import Style, PanedWindow, Button, LabelFrame, Treeview
- import pandas as pd
- from PIL import Image, ImageTk
- from tkinter import Frame
- import time
- import 明细窗口
- #先定义几个可能用到的常量
- user_name = "kkyyds"
- password = "123456"
- LEFT = "left"
- RIGHT = "right"
- TOP = "top"
- BOTTOM = "bottom"
- Song = '宋体'
- Microsoft = '微软雅黑'
-
-
- class Root: # 这是第一个页面
- def __init__(self, window):
- self.window = window
- self.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和gif
- img2 = 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 True
- else:
- messagebox.showwarning(title="登录失败", message="账号或密码错误")
- self.e2.delete(0, tk.END)
- return False
-
- def 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=1
- class Home():
- def __init__(self, window):
- self.window = window
- self.window.title(f"当前管理员为{user_name}")
- self.setup_UI()
- self.readExcel()
- self.query_result_list = []
- self.flag = action_flag
- self.update=0
- self.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):
- # 设定Style
- self.Style01 = Style()
- self.Style01.configure("TPanedwindow", background="#C9C9C9")
- self.Style01.configure("TButton", width=10, font=(Song, 15,))
- # 上边:labe
- self.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)
- # 添加右边按钮
- # LabelFrame
- self.LabelFrame_query = LabelFrame(self.Pane_right, text="学生信息查询", width=770, height=40)
- self.LabelFrame_query.place(x=5, y=5)
- # 添加控件
- y1 = 1
- y2 = -2
- self.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("<Double-1>", 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=1
- else:
- return
- def view_student(self,event):#此处event不可省略,删除后果自负
-
- # 获取Tree表格双击某一行的数据,selection()如果没有指定参数,则表明以列表形式返回所有的item
- item = 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=1
- else:
- return
- def 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=1
- else:
- return
- def save_excel(self):
- if (self.update == 0):
- showinfo("系统消息", "当前文件未作修改,无需保存")
- return
- 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]] = lst
-
- df = pd.DataFrame(dic)
- df.to_excel("学生信息.xlsx", index=False)
- # 提醒
- showinfo("系统消息", "保存成功")
- self.update=0
- except:
- 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]] = lst
-
- df = 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文库
如果收费了,记得跟我说,我把它调回来。
这么善良的作者值得你的点赞和收藏吗?