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

作者的一点感想:之前一直在研究数据结构与算法,搞得大脑特别疲劳,今天就先放松一下,做一个有点实际意义的项目,找点乐趣与成就感,不然的话很容易就撑不住,中途放弃了,python是我最早接触的一门语言,也是我学习时间和使用时间最长的一门语言,同时也是我最喜欢的一门语言,原因无他,唯有在python中感受到了写代码的乐趣,其他无论是C、C#还是Java,都只是因为学校专业课或考研工作的需要才去学习的,只有python是因为兴趣去学习的,我学习python的初衷是为了丰富自己的技能,而且写python代码的过程中我不需要去考虑原理,不需要去考虑后期的维护,完全凭借自己的心情想怎么写就怎么写,只要代码能够运行就可以,因为我清楚的明白一点,唯有python是真正给我自己使用的。

正文看这里,上方是没用废话:

本篇不适合python刚入门的人,刚入门指刚考过国二计算机python,最好在学习过爬虫、数据分析后在来看(文章中用到一点pandas的知识),因为我们在写完一个程序后(此时肯定成就感爆棚)总是想分享给别人(无形装逼),而分享给别人不能只是用pyinstaller打包吧?那实在是太low了达不到我们想要的装逼效果,这个时候你就需要一个装逼神器,没错那就是GUI用户界面,至于为什么选择tkinter而不是pyQt5,很简单因为这东西是给自己用的,python自带的tkinter完全满足需求,对于刚接触GUI的同学来说最好不要好高骛远,当然了还有一个原因是pyQt5安装太费劲了,过程中可能遇到好多问题,导致一个结果可能是还没开始学就被劝退了,所以如果你以后想要深入发展的话再去学pyQt5,或者直接去学pyQt5,当然对于我来说完全没有这个需求,tkinter足够用了,因为我只是想以后写爬虫或者其他脚本的时候用tkinter简单包装一下方便我人前显圣罢了。

好了,言归正传,学习提升最快的途径就是直接做项目,能看到这的人基础都不差,先来看看我们上半篇要达到的效果,上图:

python使用tkinter实现学生信息管理系统(上)_第1张图片 

好了,我们首先要完成的就是这两个主界面,包括登录跳转,以及第二张图中的查询功能,其他功能放在下一篇 ,登录界面的图片是我在网上找的(你也可以找自己喜欢的),虽然这辈子是考不上清华了,但这并不妨碍我做梦(哈哈),讲解以及注释代码中已经很详细了,如果实在不明白就去百度,最好参照我学习的时候使用的网址(里面的老师讲解的很好)配合我的代码一起学习(原谅我不自己进行讲解,实在是有心无力,精力有限,而且我也是参照他的,老师已经讲的很详细了,所以在此我就借花献给位帅哥美女了)

网址:Python GUI项目实战(一)登录窗体的设计与实现 - 云+社区 - 腾讯云 (tencent.com)

代码很多不要被劝退了,每个部分从头自己写的话,其实也没什么难的,原理都一样,需要注意的是每个函数的参数意义,pycharm再写tkinter的时候很坑,因为他不给参数提示,导致有很多好用的方法我最开始都不知道,都是我在网上一点点查出来的,如果你在写的过程中遇到问题,可以看看我的解决方法。比如说最开始我是没有写类的只写了函数后来发现无法解决窗口转换的问题,于是老老实实重新写了个类解决了这个问题,比如图片上传报错和上传后空白的问题等(我在代码中都做了标注,给你们避雷)

全代码如下:

import tkinter as tk
from tkinter import messagebox
from tkinter.ttk import Style, PanedWindow, Button, LabelFrame, Treeview
import pandas as pd
from PIL import Image, ImageTk
from tkinter import Frame
import time
#先定义几个可能用到的常量
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()


class Home:
    def __init__(self, window):
        self.window = window
        self.window.title(f"当前管理员为{user_name}")
        self.setup_UI()
        self.readExcel()
        self.query_result_list = []

    def readExcel(self):

        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(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(width=195, height=500, style="TPanedwindow").place(x=10, y=95)  # 这种写法下方是使用绝对距离
        self.Pane_right = PanedWindow(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").place(x=50, y=120)
        self.Button_update = Button(self.Pane_left, text="修改学生", style="TButton").place(x=50, y=160)
        self.Button_delete = Button(self.Pane_left, text="删除学生", style="TButton").place(x=50, y=200)
        self.Button_modify = Button(self.Pane_left, text="更改密码", style="TButton").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)


if __name__ == '__main__':
    root = tk.Tk()
    Root(root)

    root.mainloop()

你可能感兴趣的:(tkinter,python)