前言
学完python语法和数据库之后,想做一个用户交互的小项目,还是以常用的学生信息管理系统为例子。因为对于服务器端开发和客户端开发接触还不多,多线程也只限于简单的创建和排斥锁,所以采用常见的Tkinter模块,通过窗口的关闭也是实现单界面的限制。具体项目内容和架构见下文。
一、项目架构
1、 采用学生端和教师端,学生端提供查询成绩,个人信息,修改个人信息,评价课程,课外扩展内容
2、 教师端提供给学生科目打分,查看个人信息,修改个人信息,添加学生信息,查看课程评价
3、 主界面选择不同用户进入登录页面,登录成功进入功能页面
4、 学生由老师负责录入,课程评价由学生录入,成绩由老师录入
已解决难题:
1、旧页面关闭,新页面打开
2、登录成功之后信息页面直接显示个人信息
3、登陆成功之后显示缩小的图片(先写死图片)
4、登录信息的数据传递
5、格式化显示查询信息
模块:
1、mysql
2、tkinter
3、tkinter.messagebox
4、PIL
数据库mysql:
1、 学生信息students_info,course,course_evaluation
2、 老师信息teacher_info
存储模式:
CREATE TABLE IF NOT EXISTS student_info(
name varchar(100) NOT NULL,
age int(10),
tel varchar(11) NOT NULL,
password varchar(100) not null,
PRIMARY KEY(tel)
)ENGINE=INNODB DEFAULT CHARSET=UTF8
CREATE TABLE IF NOT EXISTS course(
course_name varchar(100) NOT NULL,
course_teacher varchar(255) NOT NULL,
PRIMARY KEY(course_name)
)ENGINE=INNODB DEFAULT CHARSET=UTF8
CREATE TABLE IF NOT EXISTS course_evaluation(
course_name varchar(100) NOT NULL,
tel varchar(11) NOT NULL,
grade int(2),
evaluation varchar(255),
tel_index INDEX(tel(11))
)ENGINE=INNODB DEFAULT CHARSET=UTF8
CREATE TABLE IF NOT EXISTS teachers_info(
name varchar(100) NOT NULL,
age int(10),
tel varchar(11) NOT NULL,
course varchar(255) NOT NULL,
password varchar(100) NOT NULL,
PRIMARY KEY(tel)
)ENGINE=INNODB DEFAULT CHARSET=UTF8
二、项目内容
1.目录结构
2.主要功能代码
主界面:
# 引用模块
from tkinter import *
from tkinter.messagebox import showinfo
import Load_menu
class MainMenu(object):
def __init__(self, window):
self.window = window
self.window.title("学生信息管理系统")
self.window.geometry('500x300')
# 定义菜单对象
menu_bar = Menu(self.window)
# 定义菜单栏标签
menu_bar.add_command(label='HELP', command=self.help_me)
menu_bar.add_command(label='VERSION', command=self.version)
menu_bar.add_separator()
self.window.config(menu=menu_bar)
# 定义页面内功能按钮
Button(self.window, text="学生登录", width=15, height=2, padx=1, pady=1, command=self.load).place(x=200, y=60)
Button(self.window, text="老师登录", width=15, height=2, padx=1, pady=1, command=self.load).place(x=200, y=120)
@staticmethod
def help_me():
showinfo('Help', 'Believe In Yourself')
@staticmethod
def version():
showinfo("Version", "@WenSheng,version-1.0.0")
def load(self):
self.window.destroy()
window1 = Tk()
Load_menu.LoadMenu(window1)
window1.mainloop()
if __name__ == "__main__":
window = Tk()
menu = MainMenu(window)
window.mainloop()
登录界面:
from tkinter import *
from tkinter.messagebox import showinfo
from Mysql_connection import *
import Teacher_menu
import Menu
import Student_menu
class LoadMenu(object):
def __init__(self, window1):
self.name = ''
self.password = ''
self.tel = ''
self.stu_data = ''
self.teach_data = ''
self.window1 = window1
self.window1.title("登录界面")
self.window1.geometry('500x300')
self.label1 = Label(self.window1, text="姓名:")
self.label1.place(x=170, y=30)
self.user_name = Entry(self.window1, show=None)
self.user_name.place(x=205, y=30)
self.label2 = Label(self.window1, text="电话:")
self.label2.place(x=170, y=70)
self.user_tel = Entry(self.window1, show=None)
self.user_tel.place(x=205, y=70)
self.label2 = Label(self.window1, text="密码:")
self.label2.place(x=170, y=110)
self.user_password = Entry(self.window1, show='*')
self.user_password.place(x=205, y=110)
Button(self.window1, text="登录", width=8, height=1, padx=1, pady=1, command=self.get_word).place(x=150, y=200)
Button(self.window1, text="返回", width=8, height=1, padx=1, pady=1, command=self.main_menu).place(x=304, y=200)
def get_word(self):
self.name = self.user_name.get()
self.password = self.user_password.get()
self.tel = self.user_tel.get()
if len(self.name) <= 0 or len(self.password) <= 0 or len(self.tel) <= 0:
showinfo("验证失败!", "请检查输入项是否完全填入!")
else:
stu_sql = "SELECT * FROM {0} WHERE name='{1}' AND tel='{2}' AND password='{3}';" \
.format(table2, self.name, self.tel, self.password)
teach_sql = "SELECT * FROM {0} WHERE name='{1}' AND tel='{2}' AND password='{3}';" \
.format(table3, self.name, self.tel, self.password)
try:
# 执行sql
curses = conn.cursor()
curses.execute(stu_sql)
# 获取数据
self.stu_data = curses.fetchall()
# 关闭临时游标
curses.close()
except Exception as e:
print("出现异常:", e)
else:
# 判断是查询结果是否有数据
if len(self.stu_data) > 0:
self.stu_menu()
else:
try:
curses1 = conn.cursor()
curses1.execute(teach_sql)
self.teach_data = curses1.fetchall()
curses1.close()
except Exception as e:
print("出现异常:", e)
else:
if len(self.teach_data) > 0:
self.teach_menu()
else:
showinfo("登录失败!", "查无此人")
def main_menu(self):
self.window1.destroy()
window = Tk()
Menu.MainMenu(window)
window.mainloop()
def teach_menu(self):
showinfo("登录成功", f"欢迎{self.name}老师")
self.window1.destroy()
window = Tk()
Teacher_menu.TeacherMenu(window, self.teach_data)
window.mainloop()
def stu_menu(self):
showinfo("Success", f"登录成功!欢迎{self.name}同学")
self.window1.destroy()
window = Tk()
Student_menu.StudentMenu(window, self.stu_data)
window.mainloop()
登录成功后的界面:
1、学生界面
from tkinter import *
from tkinter.messagebox import showerror, showinfo
from PIL import Image, ImageTk
import Menu
import Change_stu_info
import Check_course_grade
import Evaluation_course
import Side_content
class StudentMenu(object):
def __init__(self, window, stu_data):
self.stu_data = stu_data
self.window = window
self.window.title("学生信息界面")
self.window.geometry('500x300')
self.label1 = Label(self.window, text="学生基础信息:", bg="blue", font=('微软雅黑', 12))
self.label1.place(x=100, y=20)
self.text = f"""
姓名:{stu_data[0][0]}
年龄:{stu_data[0][1]}
电话:{stu_data[0][2]}
"""
self.label3 = Label(window, text=self.text, justify='left', anchor='center', font=('微软雅黑', 12), fg='green',
bg='grey', padx=15, pady=40)
self.label3.place(x=65, y=60)
self.photo = self.size_image()
self.label2 = Label(self.window, image=self.photo, compound='center')
self.label2.place(x=125, y=50)
Button(self.window, text="修改用户信息", width=12, height=1, padx=1, pady=1, command=self.change_info) \
.place(x=326, y=60)
Button(self.window, text="查询成绩信息", width=12, height=1, padx=1, pady=1, command=self.check_grade) \
.place(x=326, y=110)
Button(self.window, text="进行课程反馈", width=12, height=1, padx=1, pady=1, command=self.evaluation_course) \
.place(x=326, y=160)
Button(self.window, text="观看课外内容", width=12, height=1, padx=1, pady=1, command=self.side_content) \
.place(x=326, y=210)
Button(self.window, text="返回", width=14, height=1, bg="yellow", padx=1, pady=1, command=self.main_menu) \
.place(x=220, y=260)
@staticmethod
def size_image():
photo = Image.open("图片/student.png")
use_resize = True
if use_resize:
pil_image_small = photo.resize((50, 50), Image.ANTIALIAS)
else:
pil_image_small = photo
pil_image_small.thumbnail((50, 50), Image.ANTIALIAS)
img = ImageTk.PhotoImage(pil_image_small)
return img
def main_menu(self):
self.window.destroy()
window1 = Tk()
Menu.MainMenu(window1)
window1.mainloop()
def change_info(self):
self.window.destroy()
window1 = Tk()
Change_stu_info.ChangeInfo(window1, self.stu_data)
window1.mainloop()
def check_grade(self):
self.window.destroy()
window1 = Tk()
Check_course_grade.CheckGrade(window1, self.stu_data)
window1.mainloop()
def evaluation_course(self):
self.window.destroy()
window1 = Tk()
Evaluation_course.EvaluationGrade(window1, self.stu_data)
window1.mainloop()
def side_content(self):
self.window.destroy()
window1 = Tk()
Side_content.SideContent(window1, self.stu_data)
window1.mainloop()
2、老师界面
from tkinter import *
from Mysql_connection import *
from tkinter.messagebox import showerror, showinfo
from PIL import Image, ImageTk
import Add_student
import Remove_student
import Change_teach_info
import Set_grade
import Menu
class TeacherMenu(object):
def __init__(self, window, teach_data):
self.teach_data = teach_data
self.window = window
self.window.title("老师信息界面")
self.window.geometry('500x300')
self.text = f"""
姓名:{teach_data[0][0]}
年龄:{teach_data[0][1]}
电话:{teach_data[0][2]}
课程:{teach_data[0][3]}
"""
self.label1 = Label(self.window, text="老师基础信息:", bg="blue", font=('微软雅黑', 12))
self.label1.place(x=100, y=20)
self.lable3 = Label(window, text=self.text, justify='left', anchor='center', font=('微软雅黑', 12), fg='green',
bg='grey', padx=15, pady=30)
self.lable3.place(x=65, y=60)
self.photo = self.size_image()
self.lable2 = Label(self.window, image=self.photo, compound='center')
self.lable2.place(x=125, y=50)
Button(self.window, text="删除学生信息", width=12, height=1, padx=1, pady=1, command=self.remove_student) \
.place(x=326, y=60)
Button(self.window, text="添加学生信息", width=12, height=1, padx=1, pady=1, command=self.add_student) \
.place(x=326, y=110)
Button(self.window, text="修改个人信息", width=12, height=1, padx=1, pady=1, command=self.change_info) \
.place(x=326, y=160)
Button(self.window, text="批改学生成绩", width=12, height=1, padx=1, pady=1, command=self.set_grade) \
.place(x=326, y=210)
Button(self.window, text="返回", width=14, height=1, bg="yellow", padx=1, pady=1, command=self.main_menu) \
.place(x=220, y=260)
@staticmethod
def size_image():
photo = Image.open("图片/teach.png")
use_resize = True
if use_resize:
pil_image_small = photo.resize((50, 50), Image.ANTIALIAS)
else:
pil_image_small = photo
pil_image_small.thumbnail((50, 50), Image.ANTIALIAS)
img = ImageTk.PhotoImage(pil_image_small)
return img
def main_menu(self):
self.window.destroy()
window1 = Tk()
Menu.MainMenu(window1)
window1.mainloop()
def add_student(self):
self.window.destroy()
window1 = Tk()
Add_student.AddStudent(window1, self.teach_data)
window1.mainloop()
def remove_student(self):
self.window.destroy()
window1 = Tk()
Remove_student.RemoveStudent(window1, self.teach_data)
window1.mainloop()
def change_info(self):
self.window.destroy()
window1 = Tk()
Change_teach_info.ChangeInfo(window1, self.teach_data)
window1.mainloop()
def set_grade(self):
self.window.destroy()
window1 = Tk()
Set_grade.SetGrade(window1, self.teach_data)
window1.mainloop()
3.页面截图
其他功能就不做展示了。
总结
光阴似水,人生逆旅矣。
需要代码的可私信,因为个人项目有许多查询信息是依据数据库结构写死的,需要一定基础理解,欢迎私信交流。