用Python写一个学生管理系统(附源码)

390 阅读5分钟

微信公众号:愤怒的it男,超多Python技术干货文章。

一、前言

Python的开发方向有很多,比如爬虫采集、数据分析、机器学习等,因此Python给大家的印象都是处理数据的。实际上,Python也可以开发带有GUI界面的软件应用。这里,我就是使用Python+Tkinter写一个带有GUI界面的学生管理系统,功能齐全,代码仅200行左右。

二、作品展示

图1.PNG

三、原型设计

学生管理系统的界面分为主界面和信息输入框两部分,绝大多数操作在主界面中完成,只有增加或修改学生数据时会显示信息输入框。

(一)主界面

我将主界面分为上中下三部分:上部分为搜索条件区,用来输入搜索条件;中部分为操作按钮区,用来进行增删改查操作;下部分为数据展示区,用来展示结果数据。

图2.png

(二)信息输入框

信息输入框的原型设计就比较简单,八个接收输入的输入框,一个保存按钮。信息输入框只有点击增加或者修改按钮是才会显示。

图3.png

四、代码编写

根据解耦设计原则,我将学生管理系统的GUI界面和学生数据处理分别在ui.pystudent_manager.py两个源码文件中实现。

(一)源码文件(student_manager.py)

1、导入所需的库

import csv

2、定义学生管理类(StudentManager)

class StudentManager:

3、StudentManager中定义初始化方法

def __init__(self):
    with open('students.csv', 'r', encoding='utf-8') as file:
        csv_reader = csv.reader(file)
        self.students = [row for row in csv_reader if any(row)]

4、StudentManager中定义增加操作方法

def add(self, student):
    for s in self.students:
        if s[0] == student[0]:
            return [False, '已存在该学号学生!增加失败!']
    self.students.append(student)
    with open('students.csv', 'w', encoding='utf-8') as file:
        writer = csv.writer(file)
        writer.writerows(self.students)
    return [True, '增加成功!']

5、StudentManager中定义删除操作方法

def delete(self, student):
    for i,s in enumerate(self.students):
        if s[0] == student[0]:
            del self.students[i]
            with open('students.csv', 'w', encoding='utf-8') as file:
                writer = csv.writer(file)
                writer.writerows(self.students)
            return [True, '删除成功!']
    return [False, '不存在该学号学生!删除失败!']

6、StudentManager中定义修改操作方法

def modify(self, student):
    for i,s in enumerate(self.students):
        if s[0] == student[0]:
            self.students[i] = student
            with open('students.csv', 'w', encoding='utf-8') as file:
                writer = csv.writer(file)
                writer.writerows(self.students)
            return [True, '修改成功!']
    return [False, '不存在该学号学生!修改失败!']

7、StudentManager中定义搜索操作方法

def search(self, student):       
    condition_num = len(list(filter(lambda x: x!='', student)))
    if condition_num!=0:
        data = []
        for s in self.students:
            ok = True
            for i,v in enumerate(s):
                if student[i]!='':
                    ok = ok and (v == student[i])
            if ok:
                data.append(s)
        return data
    else:
        return self.students

8、创建一个学生管理实例(studentManager)

studentManager = StudentManager()

(二)源码文件(ui.py)

1、导入所需的库

import student_manager
import math
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox

2、创建主界面窗口

window = tk.Tk()
window.title('学籍管理系统(微信公众号:愤怒的it男)')
window.iconbitmap('favicon.ico')
window.geometry('800x400')

3、主界面窗口添加选项卡

notebook = ttk.Notebook(window)
tab1 = tk.Frame(notebook, width=800, height=380)
tab2 = tk.Frame(notebook, bg='white', width=800, height=380)
notebook.add(tab1, text='学籍管理')
notebook.add(tab2, text='其他')
notebook.pack()

4、学籍管理选项卡添加搜索条件区

frame1 = tk.Frame(tab1, bg='white')
frame1.pack()

query = [None]*8
field = ['学号','姓名','性别','年级','电话','院系','专业','备注']
columns = ["num", "name", "sex", "grade", "telephone", "department", "major", "remark"]

for i,f in enumerate(field):
    label_text = tk.Label(frame1, text=f+':', font=('宋体',10))
    label_text.grid(row=math.floor(i/4), column=i%4*2, padx=5, pady=5)

    query[i] = tk.StringVar()
    entry = tk.Entry (frame1, width=16, textvariable=query[i])
    entry.grid(row=math.floor(i/4), column=i%4*2+1, padx=5, pady=5)

5、学籍管理选项卡添加操作按钮区

def refresh_treeview(data):
    tree.delete(*tree.get_children())
    for i,item in enumerate(data):
        tree.insert("", tk.END, text=str(i+1), values=tuple(item))

frame2 = tk.Frame(tab1, width=800, height=40)
frame2.pack()

def click_add():
    popup = tk.Toplevel(window)
    createToplevel(popup, 'add', ['']*8)

button1 = tk.Button(frame2, text='增加', font=('宋体',10,'bold'), width=8, height=1, command=click_add)
button1.grid(row=0, column=0, padx=5, pady=10)

def click_delete():
    selected_items = tree.selection()
    if selected_items:
        data = tree.item(selected_items[0])['values']
        data = list(map(lambda x: str(x), data))
        result = student_manager.studentManager.delete(data)
        messagebox.showinfo(title='温馨提示', message=result[1])
        result = student_manager.studentManager.search(['']*8)
        refresh_treeview(result)
    else:
        txt = '删除失败!未选择删除数据!'
        messagebox.showinfo(title='温馨提示', message=txt)

button2 = tk.Button(frame2, text='删除', font=('宋体',10,'bold'), width=8, height=1, command=click_delete)
button2.grid(row=0, column=1, padx=5, pady=10)

def click_modify():
    selected_items = tree.selection()
    if selected_items:
        data = tree.item(selected_items[0])['values']
        data = list(map(lambda x: str(x), data))
        popup = tk.Toplevel(window)
        createToplevel(popup, 'modify', data)
    else:
        txt = '请选择需要修改的数据!'
        messagebox.showinfo(title='温馨提示', message=txt)

button3 = tk.Button(frame2, text='修改', font=('宋体',10,'bold'), width=8, height=1, command=click_modify)
button3.grid(row=0, column=2, padx=5, pady=10)

def click_search():
    data = list(map(lambda x: str(x.get()), query))
    result = student_manager.studentManager.search(data)
    refresh_treeview(result)

button4 = tk.Button(frame2, text='搜索', font=('宋体',10,'bold'), width=8, height=1, command=click_search)
button4.grid(row=0, column=3, padx=5, pady=10)

6、学籍管理选项卡添加数据展示区

frame3 = tk.Frame(tab1, bg='white', width=800, height=260)
frame3.pack()

style = ttk.Style()
style.configure("Treeview", rowheight=20)
style.configure("Treeview.Heading", font=('Arial', 11, 'bold'))

tree = ttk.Treeview(frame3, height=12, selectmode="browse", style="Treeview")
tree.pack()

tree["columns"] = tuple(columns)

tree.heading("#0", text="序号")
tree.column("#0", width=40)
for i,v in enumerate(field):
    tree.heading(columns[i], text=v)
    tree.column(columns[i], width=95, anchor="center")

result = student_manager.studentManager.search(['']*8)
refresh_treeview(result)

7、其他选项卡添加公众号图片(愤怒的it男)

image = tk.PhotoImage(file='image.png')
image_label = tk.Label(tab2, image=image)
image_label.pack()

8、创建信息输入框

def createToplevel(popup, operation, select_data):
    def on_closing():
        popup.destroy()
        window.attributes("-disabled", False)
        
    window.attributes("-disabled", True)
    popup.title("学生信息")
    popup.iconbitmap('favicon.ico')
    popup.geometry("550x150")
    popup.protocol("WM_DELETE_WINDOW", on_closing)
    
    info = [None]*8
    field = ['学号','姓名','性别','年级','电话','院系','专业','备注']

    for i,f in enumerate(field):
        label_text = tk.Label(popup, text=f+':', font=('宋体',10))
        label_text.grid(row=math.floor(i/3), column=i%3*2, padx=5, pady=5)

        info[i] = tk.StringVar()
        info[i].set(select_data[i])
        entry = tk.Entry (popup, width=16, textvariable=info[i])
        entry.grid(row=math.floor(i/3), column=i%3*2+1, padx=5, pady=5)

    def click_save(operation):
        empty_num = len(list(filter(lambda x: str(x.get())=='', info)))
        result = [False]
        if empty_num==0:
            data = list(map(lambda x: str(x.get()), info))
            if operation == 'add':
                result = student_manager.studentManager.add(data)
            if operation == 'modify':
                result = student_manager.studentManager.modify(data)  
        on_closing()
        if empty_num==0 and result[0]:
            messagebox.showinfo(title='温馨提示', message=result[1])
        elif empty_num!=0:
            txt = '保存失败!存在空字段!'
            messagebox.showinfo(title='温馨提示', message=txt)
        elif not result[0]:
            messagebox.showinfo(title='温馨提示', message=result[1])
        else:
            txt = '保存失败!存在其他异常!'
            messagebox.showinfo(title='温馨提示', message=txt)
        result = student_manager.studentManager.search(['']*8)
        refresh_treeview(result)

    button = tk.Button(popup, text='保存', font=('宋体',10,'bold'), width=8, height=1, command=lambda:click_save(operation))
    button.grid(row=3, column=3, padx=5, pady=10)

9、开启事件循环检测

window.mainloop()

五、源码下载

公众号(愤怒的it男)后台回复三位数字:001,即可获取源码资源包。

微信公众号:愤怒的it男,超多Python技术干货文章。