python使用tkinter实现学生信息管理系统(下)

前言:

原本我是不打算写下篇的,原因我也说了,没什么用纯粹是写着玩的,而且隔了好长时间了我也没什么印象了想要接上比较费时费力,但是我发现一件很神奇的事情,就是我觉得有用的文章没有太多人看,而这种花里胡哨的文章你们却很感兴趣,导致好多人问我要下篇,我想了想反正放假了也没什么事情,那就应广大网友的要求就把他补全吧(哈哈哈,想打我吗?)。

参考: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文库

如果收费了,记得跟我说,我把它调回来。

这么善良的作者值得你的点赞和收藏吗?

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>