本案例综合openpyxl(表格)模块和tkinter模块,设计自助图书馆系统,实现读者能够在系统界面“借书”、“还书”、“查询”等操作。
相关数据表格“Data.xlsx”内容如下:
功能备注:该表格能够记录读者的账号信息(包括读者号、账号密码)。登录的时候需要调取读者信息进行登录;借书的时候,将借阅书籍登记到读者的借阅记录中;还书的时候,把归还的图书从读者的借阅记录中删掉;查询的时候,能够从表格中获取读者的借阅记录显示在界面。Openpyxl模块对表格的操作可查看之前写过的文章Openpyxl表格模块操作
Windows10+python3.5.5+Vs Code(开发工具)
Data.xlsx表格(见文章最后,附完整程序和表格链接)
from tkinter import *
import openpyxl
import tkinter.messagebox as messagebox #消息弹窗
#主界面程序
top = Tk()
top.title("图书馆")
top.geometry("800x500")
main_frame = Frame(top) #主界面框架
main_frame.place(relwidth=1,relheight=1)
#布局主界面标签,按钮:借书、还书、查询、办理读者证、退出系统
Label(main_frame,text = "便民图书馆",font = ("黑体",50),width = 23,height = 3).place(x=0,y = 0)
Button(main_frame,text = "读者登录",bg = "SkyBlue",command = Sign_in,font = ("黑体",15),width = 20,height = 3).place(x= 300,y = 350)
path = "C:/Users/cos(Lin)/Desktop/" #存放路径,根据实际情况修改
#全部书籍
book_sum = {"文学":{0:"我与地坛",1:"羊脂球",2:"人生",3:"呼兰河传",4:"故乡",5:"边城",6:"朝花夕拾",7:"围城"},
"计算机":{0:"人工智能基础",1:"Python编程与机器人",2:"人工智能入门",3:"人工智能应用实战",4:"深度学习",5:"计算机网络",6:"机器学习",7:"微信小程序开发"},
"历史":{0:"万历十五年",1:"中国通史",2:"明朝那些事",3:"全球通史",4:"苏东坡传",5:"显微镜下的大明",6:"南北战争三百年",7:"宋徽宗"},
"法律":{0:"论犯罪与刑罚",1:"大国宪制",2:"民法总则",3:"民法典",4:"中国法律与中国社会",5:"民法物权",6:"刑法学定律",7:"法律的经济分析"},
"心理学":{0:"怪诞心理学",1:"乌合之众",2:"蛤蟆先生去看心理医生",3:"社会心理学",4:"心理学史导论",5:"人格心理学",6:"梦的解析",7:"也许你该找个人聊聊"},
"医学":{0:"传染病学",1:"伤寒杂病论",2:"基础护理学",3:"实用临床药物学",4:"临床诊疗指南_疼痛学分",5:"新编药物学",6:"心电图学",7:"妇产科经典病例分析"}}
#获取第一个工作表:“借阅信息”表的最大行数
sheets = openpyxl.load_workbook(path + "Data.xlsx")
sheet1 = sheets[sheets.sheetnames[0]]
max_row1 = sheet1.max_row #获取表格有效值的最后一行的行数,作为读者的编号
top.mainloop() #消息循环
#登录界面
def Sign_in():
#隐藏第一个界面,设置第二个界面
main_frame.place_forget()
second_frame = Frame(top)
second_frame.place(relwidth=1,relheight=1)
#在界面显示“读者号”“密码”的输入框,输入读者姓名
Label(second_frame,text = "登录界面",font = ("黑体",20),width = 20,height = 3).place(x=300, y=20)
Label(second_frame,text = "读者号:",font = ("黑体",18),width = 20,height = 3).place(x=100, y=100)
Label(second_frame,text = "密码:",font = ("黑体",18),width = 20,height = 3).place(x=100, y=175)
num_entry = Entry(second_frame,show = None, font=("黑体", 18), width=25) #姓名输入框
num_entry.place(x = 300,y = 135)
password_entry = Entry(second_frame,show = '*', font=("黑体", 18), width=25) #姓名输入框
password_entry.place(x = 300,y = 200)
#设置“确认”按钮,跳转到get_value()函数:该函数功能将读者与读者编号填下到第一个表格中
Button(second_frame,text = "确认",bg = "SkyBlue",font = ("黑体",12),width = 15,height = 3,command = lambda:functions(second_frame,num_entry,password_entry)).place(x= 180,y = 300)
Button(second_frame,text = "返回",bg = "SkyBlue",font = ("黑体",12),width = 15,height = 3,command = lambda:back_main(second_frame,main_frame)).place(x= 550,y = 300)
#功能界面:借书、还书、查询、退出系统功能
def functions(second_frame,num_entry,password_entry):
num = num_entry.get() #get()方法获取Entry输入框输入内容
password = password_entry.get()
print(num,password,type(num))
#隐藏第一个界面,设置第二个界面
second_frame.place_forget()
third_frame = Frame(top)
third_frame.place(relwidth=1,relheight=1)
pass_flag = 0 #验证标志位
for i in range(2,max_row1+1): #遍历表格
#验证读者号和密码是否正确。读者号在第一列,密码在第三列
if num == str(sheet1.cell(i,1).value) and password == str(sheet1.cell(i,3).value):
pass_flag = 1 #验证标志位为1
break #跳出循环
else: #密码或账号出错
pass_flag = 0 #验证标志位为0
if pass_flag == 1: #判断验证标志位
#服务功能按钮
print("验证成功")
Label(third_frame,text = str(sheet1.cell(i,2).value) + ",欢迎您",font = ("黑体",40),width = 30,height = 3).place(x=10,y = 0)
Button(third_frame,text = "借书",bg = "SkyBlue",command = lambda:Borrow_books(third_frame,num),font = ("黑体",12),width = 15,height = 3).place(x= 150,y = 200)
Button(third_frame,text = "还书",bg = "SkyBlue",command = lambda:ruturn_books(third_frame,num),font = ("黑体",12),width = 15,height = 3).place(x= 550,y = 200)
Button(third_frame,text = "查询",bg = "SkyBlue",command = lambda:Inquire(third_frame,num) ,font = ("黑体",12),width = 15,height = 3).place(x= 150,y = 350)
Button(third_frame,text = "退出",bg = "SkyBlue",font = ("黑体",12),width = 15,height = 3,command=lambda:back_main(third_frame,main_frame)).place(x= 550,y = 350)
else:
messagebox.showinfo('警告!', '密码或账号出错!') #弹出警告窗口
back_main(third_frame,second_frame) #账号密码出错则返回登录界面
#借书按钮
def Borrow_books(third_frame,num):
#隐藏第一个界面,设置第二个界面
third_frame.place_forget()
fourth_frame = Frame(top)
fourth_frame.place(relwidth=1,relheight=1)
Label(fourth_frame,text = "图书分类",font = ("黑体",40),width = 30,height = 3).place(x=10,y = 0)
Button(fourth_frame,text = "文学",bg = "white",command = lambda:BOOK(fourth_frame,num,"文学"),font = ("黑体",12),width = 15,height = 3).place(x= 150,y = 200)
Button(fourth_frame,text = "计算机",bg = "white",command = lambda:BOOK(fourth_frame,num,"计算机"),font = ("黑体",12),width = 15,height = 3).place(x= 350,y = 200)
Button(fourth_frame,text = "历史",bg = "white",command = lambda:BOOK(fourth_frame,num,"历史"),font = ("黑体",12),width = 15,height = 3).place(x= 550,y = 200)
Button(fourth_frame,text = "法律",bg = "white",command = lambda:BOOK(fourth_frame,num,"法律"),font = ("黑体",12),width = 15,height = 3).place(x= 150,y = 350)
Button(fourth_frame,text = "心理学",bg = "white",command = lambda:BOOK(fourth_frame,num,"心理学"),font = ("黑体",12),width = 15,height = 3).place(x= 350,y = 350)
Button(fourth_frame,text = "医学",bg = "white",command = lambda:BOOK(fourth_frame,num,"医学"),font = ("黑体",12),width = 15,height = 3).place(x= 550,y = 350)
#选择小说类书籍:设计复选框,可进行多本书籍选择
def BOOK(fourth_frame,num,classify):
print("classify:",classify)
print("指定书籍",book_sum["法律"])
#隐藏第一个界面,设置第二个界面
fourth_frame.place_forget()
fifth_frame = Frame(top)
fifth_frame.place(relwidth=1,relheight=1)
Label(fifth_frame,text="选择你想要借的书籍",font = ("黑体",20),fg="blue",bg="lightyellow",width=60).grid()
checkboxes = {}
for i in range (8):
checkboxes[i] = BooleanVar()
Checkbutton(fifth_frame,text=book_sum[classify][i],variable=checkboxes[i],font = ("黑体",15),height = 1).grid(row = i+1,sticky = W) #列表逐个显示书籍
Button(fifth_frame,text="确定",bg = "SkyBlue",font = ("黑体",12),width = 15,height = 3,command=lambda:selection(fifth_frame,num,checkboxes,classify)).place(x = 180, y =400)
Button(fifth_frame,text="取消",bg = "SkyBlue",font = ("黑体",12),width = 15,height = 3,command=lambda:back_main(fifth_frame,main_frame)).place(x = 550, y =400)
#确认选择的书籍,将书籍登记到借阅记录
def selection(fifth_frame,num,checkboxes,classify):
list1 = [] #定义空列表,用来存放选择借阅的书籍
for i in checkboxes:
if checkboxes[i].get() == True: #判断哪一项是否被选
list1.append(book_sum[classify][i]) #将被选项组成列表
confirm = messagebox.askokcancel('提示!','是否确认借阅?')
if confirm == True: #弹出提示借阅的窗口
for i in range(2,max_row1+1):
if sheet1.cell(i,1).value == int(num):
print(sheet1.cell(i,2).value+"借书")
#将读者选择的几本书以字符串形式,空格为间隔保存到表格中,例如 “三国演义 水浒传 西游记 红楼梦”,方法如下
sheet1.cell(i,4).value = ' '.join(list1) #将借阅书籍列表中的各个字符串元素重新组合成一个新的字符串,中间是空格
sheets.save(path + "Data.xlsx") #保存表格
messagebox.showinfo("提示!",'借阅成功,返回主界面!')
back_main(fifth_frame,main_frame)
#还书按钮
def ruturn_books(third_frame,num):
#隐藏旧界面,设置新界面
third_frame.place_forget()
fourth_frame = Frame(top)
fourth_frame.place(relwidth=1,relheight=1)
Label(fourth_frame,text = "还书服务界面",font = ("黑体",20),width = 20,height = 3).place(x=300, y=20)
Label(fourth_frame,text = "图书名称:",font = ("黑体",20),width = 20,height = 3).place(x=100, y=100)
Label(fourth_frame,text = "备注:请输入归还书籍的名称,比如朝花夕拾,每次仅输入一本哦~",font = ("楷体",12),width = 100,height = 2).place(x=30, y=180)
book_entry = Entry(fourth_frame, font=("黑体", 20), width=20) #书本输入框
book_entry.place(x = 350,y = 130)
#设置“确认”按钮,跳转到get_value()函数:该函数功能将读者与读者编号填下到第一个表格中
Button(fourth_frame,text = "确认归还",bg = "SkyBlue",font = ("黑体",12),width = 15,height = 3,command = lambda:data_val(num,book_entry)).place(x= 180,y = 300)
Button(fourth_frame,text = "返回上级",bg = "SkyBlue",font = ("黑体",12),width = 15,height = 3,command = lambda:back_main(fourth_frame,main_frame)).place(x= 550,y = 300)
#修改表格中还书数据
def data_val(num,book_entry):
borrowing_records = '' #定义读者的借阅记录
confirm = messagebox.askokcancel('提示!','是否确认归还?')
if confirm == True: #弹出提示借归还的窗口
book = book_entry.get() #获取读者输入的图书名称
for i in range(2,max_row1+1):
if num == str(sheet1.cell(i,1).value) :
reader_flag = 1 #标记位
break #定位读者在表格中的位置i,第几行
else:
reader_flag = 0 #标记位
if reader_flag == 1:
borrowing_records = str(sheet1.cell(i,4).value) #获取表格中读者的借阅记录
book_list = borrowing_records.split() #split()方法通过指定分隔符对字符串进行切片.括号内为空,即字符串按空格分割成列表,转化成列表
return_flag = 0
for k in book_list: #遍历列表
if k == str(book): #找到读者要还的书
return_flag = 1 #成功找到这本书的标志位
print("找到")
break #找到就跳出
else:
return_flag = 0 #没有找到,或者输入有误,需要提示
if return_flag == 1:
book_list.remove(k) #删除列表中这本书的记录
sheet1.cell(i,4).value = ' '.join(book_list) #将删除后的记录重新赋值到读者的借阅记录中
print(str(book_list))
sheets.save(path + "Data.xlsx") #操作表格后要记得保存数据哦
messagebox.showinfo("提示!",'还书成功!')
else:
messagebox.showinfo("提示!",'输入有误,请重新输入!')
#查询按钮函数
def Inquire(third_frame,num):
#隐藏旧界面,设置新界面
third_frame.place_forget()
fourth_frame = Frame(top)
fourth_frame.place(relwidth=1,relheight=1)
for i in range(2,max_row1+1): #遍历表格,通过输入的编号,#定位读者在表格中的位置i,第几行
if num == str(sheet1.cell(i,1).value) :
reader_flag = 1 #标记位
break
else:
reader_flag = 0 #标记位
if reader_flag == 1:
name = sheet1.cell(i,2).value #通过读者在表格中的行数,获取这名读者的名字
borrowing_records = sheet1.cell(i,4).value #通过读者在表格中的行数,获取这名读者的借阅记录
Label(fourth_frame,text = "查询服务界面",font = ("黑体",25),width = 50,height = 2).place(x=0, y=0)
Label(fourth_frame,text = "读者: " ,font = ("黑体",20),width = 15,height = 3).place(x=20, y=100) #“读者”文字标签
Label(fourth_frame,text = name ,font = ("黑体",20),fg = 'red',width =40,height = 3).place(x=200, y=100) #读者姓名
Label(fourth_frame,text = "借阅书籍: ",font = ("黑体",20),width = 15,height = 3).place(x=20, y=200) #“借阅书籍”文字标签
Label(fourth_frame,text = borrowing_records, wraplength=350, font = ("黑体",20),fg = 'red',width = 40,height = 5).place(x=200, y=200) #"借阅书籍"记录,wraplength这个参数让文字达到200像素后自动换行
Button(fourth_frame,text = "返回上级",bg = "SkyBlue",font = ("黑体",20),width = 20,height =2,command=lambda:back_main(fourth_frame,main_frame)).place(x= 300,y = 400)
#返回按钮函数
def back_main(a,main_frame):
a.place_forget()
top.geometry("800x500")
main_frame.place(relwidth=1,relheight= 1)
①第1部分主界面的程序放在所以定义的函数后面,path路经需要根据实际情况修改,
②完整程序和表格链接
链接:点我:完整程序和Data.xlsx表格
提取码:lyx4