上次草率写了一个学生管理系统登陆页面,我个人感觉我不是很完善,就在网上四处取经,然后就看到了一篇挺不错的文章,大家来康康。
效果展示
基于登录界面的补充,给其补充了图片,补充了页面的跳转。实现学生信息的展示,根据学号,姓名,电话,身份证进行粗略或详细的搜查。
代码如下(示例):
from tkinter import *
from tkinter.messagebox import showinfo
from tkinter.ttk import *
import os
import maingui
from datetime import datetime
class LoginWindow(Tk):
"""
创建登录窗体的GUI界面已经登录的方法
"""
def __init__(self):
super().__init__() # 先执行tk这个类的初始化
self.title("登录界面")
# self.geometry("620x420")
self.resizable(0,0) # 窗体大小不允许变,两个参数分别代表x轴和y轴
# self.iconbitmap('1.ico')
self["bg"] = "royalblue"
# 加载窗体
self.setup_UI()
self.file_path = "name.text" # 文件路劲
self.user_list = [] # 存储用户信息
self.var_password_error_times = 0
self.user = "" # 当前的用户
self.password = ""
# 自动执行文件中账号的加载
self.current_user_list = []
self.load_file_info( )
def setup_UI(self):
# ttk中控件使用style对象设定
self.Style01 = Style()
self.Style01.configure("user.TLabel",font = ("华文黑体",20,"bold"),foreground = "royalblue")
self.Style01.configure("TEntry",font = ("华文黑体",20,"bold"))
self.Style01.configure("TButton",font = ("华文黑体",20,"bold"),foreground = "royalblue")
# 创建一个Label标签展示图片
self.Login_image = PhotoImage(file ="1.png")
self.Label_image = Label(self,image = self.Login_image)
self.Label_image.pack(padx = 5,pady = 5)
# 创建一个Label标签 + Entry --- 用户名
self.Label_user = Label(self,text = "用户名:", style = "user.TLabel")
self.Label_user.pack(side = LEFT,padx = 25,pady = 5)
self.var_user = StringVar( )
self.Entry_user = Entry(self, width=15, textvariable=self.var_user, style="TEntry")
self.Entry_user.pack(side=LEFT, padx=5, pady=8)
# 创建一个Label标签 + Entry --- 密码
self.Label_password = Label(self, text="密码:", style="user.TLabel")
self.Label_password.pack(side=LEFT, padx=15, pady=5)
self.var_password = StringVar( )
self.Entry_password = Entry(self, width=15, textvariable=self.var_password, show="*",
style="TEntry") # 密码以什么符号显示,使用show方法
self.Entry_password.pack(side=LEFT, padx=5, pady=8)
# 创建一个按钮 --- 登录
self.Button_login = Button(self, text="登录", width=7, command=self.login)
self.Button_login.pack(side=LEFT, padx=20, pady=5)
def load_file_info(self):
"""
读取用户名、密码、状态
:return:
"""
if not os.path.exists(self.file_path):
showinfo("系统消息", "提供的文件名不存在!")
else:
try:
with open(file=self.file_path, mode="r") as fd:
# 一次读一行
current_line = fd.readline( )
while current_line:
temp_list = current_line.split(",") # 长字符串分割层三个
self.user_list.append(temp_list)
# 读取下一行,读完了循环就结束了
current_line = fd.readline( )
except:
showinfo("系统消息", "文件读取出现异常!")
def login(self):
# 获取用户的用户名和密码
self.user = self.var_user.get()
self.password = self.var_password.get()
# 实现身份验证,遍历用户信息列表
for index in range(len(self.user_list)):
# 用户名是否正确
if self.user.strip().lower() == str(self.user_list[index][0]).strip().lower():
# 判断账号是否被禁用
if "0" in str(self.user_list[index][2]).strip().lower():
showinfo("系统消息", "账号已禁用,请联系管理员")
break
# 密码是否正确
if self.password != str(self.user_list[index][1]).strip().lower():
self.var_password_error_times += 1
# 判读错误是否到三次
if self.var_password_error_times >= 3:
showinfo("系统消息","密码错误已达三次,账号已锁定!")
# 改变状态
self.user_list[index][2] = "0\n"
# 信息写入到文件
self.write_file_info()
else:
showinfo("系统消息", "输入的密码错误")
# 判断成功后整个循环退出,不要执行后面的判断用户名不存在的语句了
break
else:
# 如果在三次之内输入正确了,把错误次数归零
self.var_password_error_times = 0
# 把用户名和密码写入list
self.current_user_list = self.user_list[index]
# 加载主窗体
self.load_main()
# showinfo("系统消息", "登录成功!")
break
# 如果校验到最后都没有相同的用户名,则用户名不存在
if index == len(self.user_list) - 1:
showinfo("系统消息","输入的用户名不存在")
def load_main(self):
# 关闭当前窗体
self.destroy( )
# 加载新窗体
main_window = maingui.MainWindow(self.current_user_list,self.get_now_time())
def get_now_time(self):
today = datetime.today( )
return ("%04d-%02d-%02d %02d:%02d:%02d" % (today.year,
today.month, today.day, today.hour, today.minute, today.second))
def write_file_info(self):
# 1.清空文件;2.写入
try:
with open(file=self.file_path, mode="w") as fd:
fd.write("")
with open(file=self.file_path, mode="a") as fd:
for item in self.user_list:
fd.write(",".join(item))
except:
showinfo("系统消息", "写入文件出现异常")
if __name__ == '__main__':
this_login = LoginWindow()
this_login.mainloop()
代码如下(示例):
maingui.py
from tkinter import *
from tkinter.messagebox import showinfo, askyesno
from tkinter.ttk import *
import os
import detailgui
# import changepasswordgui
class MainWindow(Tk):
def __init__(self, current_user_list, current_time):
super().__init__()
self.title("主窗体")
self.geometry("900x640+180+80")
self.resizable(0,0)
self["bg"]="skyblue"
self.login_time = current_time
self.current_student_list = []
self.query_result_list = []
self.action_flag = 0
self.current_login_list = current_user_list
# 存储学生信息
self.all_student_list = []
self.file_path = "studerts.text"
# 加载gui
self.setup_UI( )
# 自动执行的函数
self.load_file_student_info( ) # 自动把学生信息写入到all_student_list中
self.load_treeview(self.all_student_list) # 把所有学生信息加载到TreeView中
# 把窗体的行为捕获转为方法
self.protocol("WM_DELETE_WINDOW", self.close_window)
def setup_UI(self):
# 设定Style
self.Style01 = Style()
self.Style01.configure("left.TPanedwindow",background = "navy")
self.Style01.configure("right.TPanedwindow", background="skyblue")
self.Style01.configure("TButton",width = 10,font = ("华文黑体",15,"bold"))
# Top_banner
self.Login_image = PhotoImage(file = "zhuti2.png")
self.Lable_image = Label(self,image = self.Login_image)
self.Lable_image.pack()
# 加载当前用户和时间
self.Label_login_user = Label(self, text="当前用户:" + str(self.current_login_list[0]).title( )
+ "\n登录时间:" + self.login_time)
self.Label_login_user.place(x=700, y=40)
# 左边:按钮区域,创建一个容器
self.Pane_left = PanedWindow(width = 200,height = 540,style = "left.TPanedwindow")
self.Pane_left.place(x = 4,y = 94)
self.Pane_right = PanedWindow(width=685, height=540,style = "right.TPanedwindow")
self.Pane_right.place(x = 210,y = 94)
# 添加左边按钮
self.Button_add = Button(self.Pane_left, text="添加学生", style="TButton", command=self.add_student)
self.Button_add.place(x=20, y=20)
self.Button_update = Button(self.Pane_left, text="修改学生", style="TButton", command=self.update_student)
self.Button_update.place(x=20, y=60)
self.Button_delete = Button(self.Pane_left, text="删除学生", style="TButton", command=self.delete_student)
self.Button_delete.place(x=20, y=100)
self.Button_modify = Button(self.Pane_left, text="更改密码", style="TButton", command=self.load_change_password)
self.Button_modify.place(x=20, y=160)
# 右边:查询、TreeView
self.Pane_right = PanedWindow(width=725, height=540, style="right.TPanedwindow")
self.Pane_right.place(x=170, y=94)
# LabelFrame
self.LabelFrame_query = LabelFrame(self.Pane_right, text="学生信息查询", width=680, height=70)
self.LabelFrame_query.place(x=10, y=10)
# 添加控件
self.Label_sno = Label(self.LabelFrame_query, text="学号:")
self.Label_sno.place(x=5, y=13)
self.var_sno = StringVar()
self.Entry_sno = Entry(self.LabelFrame_query, width=8)
self.Entry_sno.place(x=40, y=10)
self.Label_name = Label(self.LabelFrame_query, text="姓名:")
self.Label_name.place(x=125, y=13)
self.var_name = StringVar( )
self.Entry_name = Entry(self.LabelFrame_query, width=8)
self.Entry_name.place(x=160, y=10)
self.Label_mobile = Label(self.LabelFrame_query, text="电话:")
self.Label_mobile.place(x=245, y=13)
self.var_mobile = StringVar()
self.Entry_mobile = Entry(self.LabelFrame_query, width=8)
self.Entry_mobile.place(x=280, y=10)
self.Label_id = Label(self.LabelFrame_query, text="身份证:")
self.Label_id.place(x=365, y=13)
self.var_id = StringVar( )
self.Entry_id = Entry(self.LabelFrame_query, width=10, textvariable=self.var_id)
self.Entry_id.place(x=420, y=10)
self.Button_query = Button(self.LabelFrame_query, text="查询", width=4, command=self.get_query_result)
self.Button_query.place(x=510, y=10)
self.Button_all = Button(self.LabelFrame_query, text="显示全部", width=8, command=self.load_all_student)
self.Button_all.place(x=570, y=10)
# 添加TreeView控件
self.Tree = Treeview(self.Pane_right, columns=("sno", "names",
"gender", "birthday", "mobile", "email", "address"),
show="headings", height=20)
# 设置每一个列的宽度和对齐的方式
self.Tree.column("sno", width=100, anchor="center")
self.Tree.column("names", width=80, anchor="center")
self.Tree.column("gender", width=80, anchor="center")
self.Tree.column("birthday", width=100, anchor="center")
self.Tree.column("mobile", width=100, anchor="center")
self.Tree.column("email", width=100, anchor="center")
self.Tree.column("address", width=120, anchor="center")
# 设置每个列的标题
self.Tree.heading("sno", text="学号")
self.Tree.heading("names", text="姓名")
self.Tree.heading("gender", text="性别")
self.Tree.heading("birthday", text="生日")
self.Tree.heading("mobile", text="手机号码")
self.Tree.heading("email", text="邮箱地址")
self.Tree.heading("address", text="家庭住址")
self.Tree.place(x=10, y=80)
self.Tree.bind("" , self.view_student)
def load_file_student_info(self):
if not os.path.exists(self.file_path):
showinfo("系统消息", "提供的文件名不存在!")
else:
try:
with open(file=self.file_path, mode="r",encoding="UTF-8") as fd:
# 一次读一行
current_line = fd.readline()
while current_line:
temp_list = current_line.split(",") # 长字符串分割层三个
self.all_student_list.append(temp_list)
# 读取下一行,读完了循环就结束了
current_line = fd.readline()
except:
showinfo("系统消息", "文件读取出现异常!")
def load_treeview(self, current_list: list):
# 每次调用之前,需要先把treeview中的内容清空
for i in self.Tree.get_children( ):
self.Tree.delete(i)
# 判断是否有数据:
if len(current_list) == 0:
showinfo("系统消息", "没有数据加载")
else:
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):
"""
针对学生信息进行查询
:return:
"""
# 清空query_result_list
self.query_result_list.clear()
# 准备查询条件,去空格后往列表中添加数据
query_condition = []
query_condition.append(self.Entry_sno.get().strip()) # 采集学号信息
query_condition.append(self.Entry_name.get().strip()) # 采集姓名信息
query_condition.append(self.Entry_mobile.get().strip()) # 采集手机号码信息
query_condition.append(self.Entry_id.get().strip()) # 采集身份证号码信息
# 遍历List获取符合条件的学生信息
for item in self.all_student_list:
if query_condition[0] in item[0] and query_condition[1] in item[1] and \
query_condition[2] in item[4] and query_condition[3] in item[7]:
# 满足条件的学生
self.query_result_list.append(item)
# 把结果加载的TreeView中
self.load_treeview(self.query_result_list)
def load_all_student(self):
# 把所有条件文本框清空
self.var_sno.set("")
self.var_name.set("")
self.var_mobile.set("")
self.var_id.set("")
# 加载所有的学生信息到treeview
self.load_treeview(self.all_student_list)
def load_detail_window(self):
detail_window = detailgui.DetailWindow(self.action_flag, self.current_student_list, self.all_student_list)
self.wait_window(detail_window)
return detail_window.userinfo
def add_student(self):
self.action_flag = 2
if self.load_detail_window() == 1:
self.load_all_student()
else:
return
def update_student(self):
self.action_flag = 3
try:
item = self.Tree.selection()[0]
Temp_student_list = self.Tree.item(item, "values")
# 遍历获得完整学生明细信息
for item in self.all_student_list:
if item[0] == Temp_student_list[0]:
self.current_student_list = item
# 载入窗体
if self.load_detail_window() == 1:
self.load_all_student()
else:
return
except:
showinfo("系统消息","请先选中学生再修改")
def view_student(self, event):
self.action_flag = 1
# 获取Tree表格双击某一行的数据,selection()如果没有指定参数,则表明以列表形式返回所有的item
item = self.Tree.selection()[0] # 获取双击某一行的项目标识符
# 这个Tree表格中的数据,只是显示了部分数据,为了显示明细窗体,我们需要加载文件中的读取出来的完整信息
Temp_student_list = self.Tree.item(item, "values") # 通过item方法,获取该列的所有元素,以元组的形式返回
# 遍历获得完整学生明细信息
for item in self.all_student_list:
if item[0] == Temp_student_list[0]:
self.current_student_list = item
self.load_detail_window()
def delete_student(self):
try:
# 获取选中的学生
item = self.Tree.selection()[0]
Temp_student_list = self.Tree.item(item, "values")
# 询问是否删除
choose = askyesno("删除确认", "确定要删除该学生【学号:" + Temp_student_list[0] + ",姓名:" +
Temp_student_list[1] + "】的信息吗?")
if choose:
# 执行删除动作
for index in range(len(self.all_student_list)):
if self.all_student_list[index][0] == Temp_student_list[0]:
self.all_student_list.pop(index)
break
# 更新表格
self.load_all_student()
showinfo("系统消息", "删除成功!")
else:
return
except:
showinfo("系统消息", "请先选中学生再删除")
def close_window(self):
# 给用户提示:是否要保存数据
choose = askyesno("关闭前提醒", "关闭窗体前是否要将修改写入文件")
if choose:
try:
with open(self.file_path, mode="w", encoding="UTF-8") as fd:
fd.write("")
with open(self.file_path, mode="w", encoding="UTF-8") as fd:
for item in self.all_student_list:
temp = ",".join(item)
temp = temp.replace("\n", "") + "\n"
fd.write(temp)
except:
showinfo("系统消息", "写入文件出现异常")
# 提醒
showinfo("系统消息", "所有的修改已经写入到文件")
# 关闭
self.destroy()
else:
self.destroy()
该中使用的图片为自己根据尺寸制造
本文章仅供对tkinter模块的学习,想要详细了解,请访问链接: link。